From 8f4e1eca413cb767574fc4eed7530044bd391832 Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Sun, 4 Dec 2022 11:26:55 +0000 Subject: [PATCH] remove imageproc dependency --- Cargo.lock | 265 +------------------------------------- Cargo.toml | 1 - src/font.rs | 5 +- src/imageproc.rs | 327 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/utils.rs | 70 +--------- 6 files changed, 339 insertions(+), 330 deletions(-) create mode 100644 src/imageproc.rs diff --git a/Cargo.lock b/Cargo.lock index 1902b84..a1f25ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6" - [[package]] name = "adler" version = "1.0.2" @@ -29,15 +23,6 @@ version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - [[package]] name = "atty" version = "0.2.14" @@ -509,17 +494,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.7" @@ -528,7 +502,7 @@ checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -590,24 +564,6 @@ dependencies = [ "png", ] -[[package]] -name = "imageproc" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aee993351d466301a29655d628bfc6f5a35a0d062b6160ca0808f425805fd7" -dependencies = [ - "approx", - "conv", - "image", - "itertools", - "nalgebra", - "num", - "rand", - "rand_distr", - "rayon", - "rusttype", -] - [[package]] name = "indexmap" version = "1.9.1" @@ -627,15 +583,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.4" @@ -706,15 +653,6 @@ dependencies = [ "libc", ] -[[package]] -name = "matrixmultiply" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" -dependencies = [ - "rawpointer", -] - [[package]] name = "memoffset" version = "0.6.5" @@ -733,55 +671,6 @@ dependencies = [ "adler", ] -[[package]] -name = "nalgebra" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb2d0de08694bed883320212c18ee3008576bfe8c306f4c3c4a58b4876998be" -dependencies = [ - "approx", - "matrixmultiply", - "num-complex", - "num-rational", - "num-traits", - "simba", - "typenum", -] - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" -dependencies = [ - "num-traits", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -792,17 +681,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.1" @@ -810,7 +688,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", - "num-bigint", "num-integer", "num-traits", ] @@ -911,21 +788,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "owned_ttf_parser" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "paste" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" - [[package]] name = "pasteboard" version = "0.1.3" @@ -998,12 +860,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1046,62 +902,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_distr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" -dependencies = [ - "rand", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - [[package]] name = "rayon" version = "1.5.3" @@ -1141,7 +941,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.7", + "getrandom", "redox_syscall", "thiserror", ] @@ -1170,31 +970,12 @@ dependencies = [ "semver", ] -[[package]] -name = "rusttype" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - [[package]] name = "ryu" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" -[[package]] -name = "safe_arch" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" -dependencies = [ - "bytemuck", -] - [[package]] name = "safemem" version = "0.3.3" @@ -1284,7 +1065,6 @@ dependencies = [ "font-kit", "harfbuzz-sys", "image", - "imageproc", "lazy_static", "log", "pasteboard", @@ -1296,19 +1076,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "simba" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48e45e5961033db030b56ad67aef22e9c908c493a6e8348c0a0f6b93433cd77" -dependencies = [ - "approx", - "num-complex", - "num-traits", - "paste", - "wide", -] - [[package]] name = "str-buf" version = "1.0.6" @@ -1453,18 +1220,6 @@ dependencies = [ "num_threads", ] -[[package]] -name = "ttf-parser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - [[package]] name = "ucd-trie" version = "0.1.5" @@ -1512,28 +1267,12 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wide" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae41ecad2489a1655c8ef8489444b0b113c0a0c795944a3572a0931cf7d2525c" -dependencies = [ - "bytemuck", - "safe_arch", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index ee411aa..1b540f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ harfbuzz = ["harfbuzz-sys", "font-kit/loader-freetype-default", "font-kit/source [dependencies] dirs = "4.0" -imageproc = "0.23.0" clipboard = "0.5.0" tempfile = "3.1.0" conv = "0.3.3" diff --git a/src/font.rs b/src/font.rs index 7f8e43c..11c19ac 100644 --- a/src/font.rs +++ b/src/font.rs @@ -14,6 +14,7 @@ use crate::error::FontError; #[cfg(feature = "harfbuzz")] use crate::hb_wrapper::{feature_from_tag, HBBuffer, HBFont}; +use crate::imageproc::{weighted_sum, Clamp}; use anyhow::Result; use conv::ValueInto; use font_kit::canvas::{Canvas, Format, RasterizationOptions}; @@ -22,8 +23,6 @@ use font_kit::hinting::HintingOptions; use font_kit::properties::{Properties, Style, Weight}; use font_kit::source::SystemSource; use image::{GenericImage, Pixel}; -use imageproc::definitions::Clamp; -use imageproc::pixelops::weighted_sum; use pathfinder_geometry::transform2d::Transform2F; use std::collections::HashMap; use std::sync::Arc; @@ -348,7 +347,7 @@ impl FontCollection { ) -> u32 where I: GenericImage, - ::Subpixel: ValueInto + Clamp, + ::Subpixel: ValueInto + Clamp, { let metrics = self.0[0].get_regular().metrics(); let offset = diff --git a/src/imageproc.rs b/src/imageproc.rs new file mode 100644 index 0000000..1c46241 --- /dev/null +++ b/src/imageproc.rs @@ -0,0 +1,327 @@ +//! Manual implementations of some things from imageproc - without all the unnecessary faff +//! +//! The MIT License (MIT) +//! +//! Copyright (c) 2015 PistonDevelopers +//! +//! Permission is hereby granted, free of charge, to any person obtaining a copy +//! of this software and associated documentation files (the "Software"), to deal +//! in the Software without restriction, including without limitation the rights +//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//! copies of the Software, and to permit persons to whom the Software is +//! furnished to do so, subject to the following conditions: +//! +//! The above copyright notice and this permission notice shall be included in all +//! copies or substantial portions of the Software. +//! +//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//! SOFTWARE. + +use conv::ValueInto; +use image::{GenericImage, Pixel, Rgba, RgbaImage}; + +/// Draw as much of a circle, including its contents, as lies inside the image bounds. +pub(crate) fn draw_filled_circle_mut( + image: &mut I, + center: (i32, i32), + radius: i32, + color: I::Pixel, +) where + I: GenericImage, + I::Pixel: 'static, +{ + let mut x = 0i32; + let mut y = radius; + let mut p = 1 - radius; + let x0 = center.0; + let y0 = center.1; + + while x <= y { + draw_line_segment_mut( + image, + ((x0 - x) as f32, (y0 + y) as f32), + ((x0 + x) as f32, (y0 + y) as f32), + color, + ); + draw_line_segment_mut( + image, + ((x0 - y) as f32, (y0 + x) as f32), + ((x0 + y) as f32, (y0 + x) as f32), + color, + ); + draw_line_segment_mut( + image, + ((x0 - x) as f32, (y0 - y) as f32), + ((x0 + x) as f32, (y0 - y) as f32), + color, + ); + draw_line_segment_mut( + image, + ((x0 - y) as f32, (y0 - x) as f32), + ((x0 + y) as f32, (y0 - x) as f32), + color, + ); + + x += 1; + if p < 0 { + p += 2 * x + 1; + } else { + y -= 1; + p += 2 * (x - y) + 1; + } + } +} + +/// Draws a line segment on an image in place. +/// +/// Draws as much of the line segment between start and end as lies inside the image bounds. +/// +/// Uses [Bresenham's line drawing algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm). +pub(crate) fn draw_line_segment_mut( + canvas: &mut I, + start: (f32, f32), + end: (f32, f32), + color: I::Pixel, +) where + I: GenericImage, + I::Pixel: 'static, +{ + let (width, height) = canvas.dimensions(); + let in_bounds = |x, y| x >= 0 && x < width as i32 && y >= 0 && y < height as i32; + + let line_iterator = BresenhamLineIter::new(start, end); + + for point in line_iterator { + let x = point.0; + let y = point.1; + + if in_bounds(x, y) { + canvas.put_pixel(x as u32, y as u32, color); + } + } +} + +/// Iterates over the coordinates in a line segment using +/// [Bresenham's line drawing algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm). +struct BresenhamLineIter { + dx: f32, + dy: f32, + x: i32, + y: i32, + error: f32, + end_x: i32, + is_steep: bool, + y_step: i32, +} + +impl BresenhamLineIter { + /// Creates a [`BresenhamLineIter`](struct.BresenhamLineIter.html) which will iterate over the integer coordinates + /// between `start` and `end`. + fn new(start: (f32, f32), end: (f32, f32)) -> BresenhamLineIter { + let (mut x0, mut y0) = (start.0, start.1); + let (mut x1, mut y1) = (end.0, end.1); + + let is_steep = (y1 - y0).abs() > (x1 - x0).abs(); + if is_steep { + std::mem::swap(&mut x0, &mut y0); + std::mem::swap(&mut x1, &mut y1); + } + + if x0 > x1 { + std::mem::swap(&mut x0, &mut x1); + std::mem::swap(&mut y0, &mut y1); + } + + let dx = x1 - x0; + + BresenhamLineIter { + dx, + dy: (y1 - y0).abs(), + x: x0 as i32, + y: y0 as i32, + error: dx / 2f32, + end_x: x1 as i32, + is_steep, + y_step: if y0 < y1 { 1 } else { -1 }, + } + } +} + +impl Iterator for BresenhamLineIter { + type Item = (i32, i32); + + fn next(&mut self) -> Option<(i32, i32)> { + if self.x > self.end_x { + None + } else { + let ret = if self.is_steep { + (self.y, self.x) + } else { + (self.x, self.y) + }; + + self.x += 1; + self.error -= self.dy; + if self.error < 0f32 { + self.y += self.y_step; + self.error += self.dx; + } + + Some(ret) + } + } +} + +/// Draws a rectangle and its contents on an image in place. +/// +/// Draws as much of the rectangle and its contents as lies inside the image bounds. +pub(crate) fn draw_filled_rect_mut(canvas: &mut RgbaImage, rect: Rect, color: Rgba) { + let canvas_bounds = Rect { + left: 0, + top: 0, + width: canvas.width(), + height: canvas.height(), + }; + if let Some(intersection) = canvas_bounds.intersect(rect) { + for dy in 0..intersection.height { + for dx in 0..intersection.width { + let x = intersection.left as u32 + dx; + let y = intersection.top as u32 + dy; + canvas.put_pixel(x, y, color); + } + } + } +} + +/// A rectangular region of non-zero width and height. +/// # Examples +/// ``` +/// use imageproc::rect::Rect; +/// use imageproc::rect::Region; +/// +/// // Construct a rectangle with top-left corner at (4, 5), width 6 and height 7. +/// let rect = Rect::at(4, 5).of_size(6, 7); +/// +/// // Contains top-left point: +/// assert_eq!(rect.left(), 4); +/// assert_eq!(rect.top(), 5); +/// assert!(rect.contains(rect.left(), rect.top())); +/// +/// // Contains bottom-right point, at (left + width - 1, top + height - 1): +/// assert_eq!(rect.right(), 9); +/// assert_eq!(rect.bottom(), 11); +/// assert!(rect.contains(rect.right(), rect.bottom())); +/// ``` +pub(crate) struct Rect { + pub(crate) left: i32, + pub(crate) top: i32, + pub(crate) width: u32, + pub(crate) height: u32, +} + +impl Rect { + /// Greatest y-coordinate reached by rect. + fn bottom(&self) -> i32 { + self.top + (self.height as i32) - 1 + } + + /// Greatest x-coordinate reached by rect. + fn right(&self) -> i32 { + self.left + (self.width as i32) - 1 + } + + /// Returns the intersection of self and other, or none if they are are disjoint. + fn intersect(&self, other: Rect) -> Option { + let left = std::cmp::max(self.left, other.left); + let top = std::cmp::max(self.top, other.top); + let right = std::cmp::min(self.right(), other.right()); + let bottom = std::cmp::min(self.bottom(), other.bottom()); + + if right < left || bottom < top { + return None; + } + + Some(Rect { + left, + top, + width: (right - left) as u32 + 1, + height: (bottom - top) as u32 + 1, + }) + } +} + +/// Adds pixels with the given weights. Results are clamped to prevent arithmetical overflows. +/// +/// # Examples +/// ``` +/// # extern crate image; +/// # extern crate imageproc; +/// # fn main() { +/// use image::Rgb; +/// use imageproc::pixelops::weighted_sum; +/// +/// let left = Rgb([10u8, 20u8, 30u8]); +/// let right = Rgb([100u8, 80u8, 60u8]); +/// +/// let sum = weighted_sum(left, right, 0.7, 0.3); +/// assert_eq!(sum, Rgb([37, 38, 39])); +/// # } +/// ``` +pub(crate) fn weighted_sum(left: P, right: P, left_weight: f32, right_weight: f32) -> P +where + P::Subpixel: ValueInto + Clamp, +{ + left.map2(&right, |p, q| { + Clamp::clamp(cast(p) * left_weight + cast(q) * right_weight) + }) +} + +fn cast(x: T) -> U +where + T: ValueInto, +{ + match x.value_into() { + Ok(y) => y, + Err(_) => panic!("Failed to convert"), + } +} + +/// A type to which we can clamp a value of type f32. +/// Implementations are not required to handle `NaN`s gracefully. +pub trait Clamp { + /// Clamp `x` to a valid value for this type. + fn clamp(x: f32) -> Self; +} + +/// Creates an implementation of Clamp for type To. +macro_rules! implement_clamp { + ($to:ty) => { + impl Clamp for $to { + fn clamp(x: f32) -> $to { + if x < <$to>::MAX as f32 { + if x > <$to>::MIN as f32 { + x as $to + } else { + <$to>::MIN + } + } else { + <$to>::MAX + } + } + } + }; +} + +impl Clamp for f32 { + fn clamp(x: f32) -> f32 { + x + } +} + +implement_clamp!(u8); +implement_clamp!(u16); diff --git a/src/lib.rs b/src/lib.rs index 67551d8..dbc946a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,3 +46,4 @@ pub mod formatter; #[cfg(feature = "harfbuzz")] pub mod hb_wrapper; pub mod utils; +mod imageproc; diff --git a/src/utils.rs b/src/utils.rs index 4214099..8642b99 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,8 @@ use crate::error::ParseColorError; +use crate::imageproc::{draw_filled_circle_mut, draw_filled_rect_mut, Rect}; use image::imageops::{crop_imm, resize, FilterType}; use image::Pixel; use image::{DynamicImage, GenericImage, GenericImageView, Rgba, RgbaImage}; -use imageproc::drawing::{draw_filled_rect_mut, draw_line_segment_mut}; -use imageproc::rect::Rect; pub trait ToRgba { type Target; @@ -212,11 +211,12 @@ impl ShadowAdder { // create the shadow let mut shadow = self.background.to_image(width, height); if self.blur_radius > 0.0 { - let rect = Rect::at( - self.pad_horiz as i32 + self.offset_x, - self.pad_vert as i32 + self.offset_y, - ) - .of_size(image.width(), image.height()); + let rect = Rect { + left: self.pad_horiz as i32 + self.offset_x, + top: self.pad_vert as i32 + self.offset_y, + width: image.width(), + height: image.height(), + }; draw_filled_rect_mut(&mut shadow, rect, self.shadow_color); @@ -300,62 +300,6 @@ pub(crate) fn round_corner(image: &mut DynamicImage, radius: u32) { .unwrap(); } -// `draw_filled_circle_mut` doesn't work well with small radius in imageproc v0.18.0 -// it has been fixed but still have to wait for releasing -// issue: https://github.com/image-rs/imageproc/issues/328 -// PR: https://github.com/image-rs/imageproc/pull/330 -/// Draw as much of a circle, including its contents, as lies inside the image bounds. -pub(crate) fn draw_filled_circle_mut( - image: &mut I, - center: (i32, i32), - radius: i32, - color: I::Pixel, -) where - I: GenericImage, - I::Pixel: 'static, -{ - let mut x = 0i32; - let mut y = radius; - let mut p = 1 - radius; - let x0 = center.0; - let y0 = center.1; - - while x <= y { - draw_line_segment_mut( - image, - ((x0 - x) as f32, (y0 + y) as f32), - ((x0 + x) as f32, (y0 + y) as f32), - color, - ); - draw_line_segment_mut( - image, - ((x0 - y) as f32, (y0 + x) as f32), - ((x0 + y) as f32, (y0 + x) as f32), - color, - ); - draw_line_segment_mut( - image, - ((x0 - x) as f32, (y0 - y) as f32), - ((x0 + x) as f32, (y0 - y) as f32), - color, - ); - draw_line_segment_mut( - image, - ((x0 - y) as f32, (y0 - x) as f32), - ((x0 + y) as f32, (y0 - x) as f32), - color, - ); - - x += 1; - if p < 0 { - p += 2 * x + 1; - } else { - y -= 1; - p += 2 * (x - y) + 1; - } - } -} - #[cfg(test)] mod tests { use crate::utils::ToRgba;