mirror of https://github.com/Aloxaf/silicon
Compare commits
2 Commits
2b745027c3
...
319066e9a1
Author | SHA1 | Date |
---|---|---|
Aloxaf | 319066e9a1 | |
Aloxaf | a460f0a152 |
|
@ -680,9 +680,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.3"
|
||||
version = "2.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
|
||||
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
@ -726,12 +726,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
|||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
|
||||
checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -768,9 +768,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
|
@ -1017,8 +1017,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "pathfinder_simd"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0444332826c70dc47be74a7c6a5fc44e23a7905ad6858d4162b658320455ef93"
|
||||
source = "git+https://github.com/servo/pathfinder#cb4eb597c3fef886417e2ff7b89e8348a131b417"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
@ -1306,7 +1305,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.51",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1414,9 +1413,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.51"
|
||||
version = "2.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1494,7 +1493,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.51",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1578,9 +1577,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
|
@ -1654,7 +1653,7 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.3",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1674,17 +1673,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.3",
|
||||
"windows_aarch64_msvc 0.52.3",
|
||||
"windows_i686_gnu 0.52.3",
|
||||
"windows_i686_msvc 0.52.3",
|
||||
"windows_x86_64_gnu 0.52.3",
|
||||
"windows_x86_64_gnullvm 0.52.3",
|
||||
"windows_x86_64_msvc 0.52.3",
|
||||
"windows_aarch64_gnullvm 0.52.4",
|
||||
"windows_aarch64_msvc 0.52.4",
|
||||
"windows_i686_gnu 0.52.4",
|
||||
"windows_i686_msvc 0.52.4",
|
||||
"windows_x86_64_gnu 0.52.4",
|
||||
"windows_x86_64_gnullvm 0.52.4",
|
||||
"windows_x86_64_msvc 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1695,9 +1694,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
@ -1707,9 +1706,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -1719,9 +1718,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
@ -1731,9 +1730,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
@ -1743,9 +1742,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
@ -1755,9 +1754,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -1767,9 +1766,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.3"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
[[package]]
|
||||
name = "wio"
|
||||
|
|
|
@ -63,3 +63,6 @@ pasteboard = "0.1.3"
|
|||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
clipboard-win = "5.2.0"
|
||||
image = { version = "0.24", default-features = false, features = ["jpeg", "bmp", "jpeg_rayon"] }
|
||||
|
||||
[patch.crates-io]
|
||||
pathfinder_simd = { version = "0.5.0", git = "https://github.com/servo/pathfinder" }
|
||||
|
|
|
@ -2,6 +2,7 @@ use anyhow::{Context, Error};
|
|||
use clipboard::{ClipboardContext, ClipboardProvider};
|
||||
use image::Rgba;
|
||||
use silicon::directories::PROJECT_DIRS;
|
||||
use silicon::font::FontCollection;
|
||||
use silicon::formatter::{ImageFormatter, ImageFormatterBuilder};
|
||||
use silicon::utils::{Background, ShadowAdder, ToRgba};
|
||||
use std::ffi::OsString;
|
||||
|
@ -269,7 +270,7 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_formatter(&self) -> Result<ImageFormatter, Error> {
|
||||
pub fn get_formatter(&self) -> Result<ImageFormatter<FontCollection>, Error> {
|
||||
let formatter = ImageFormatterBuilder::new()
|
||||
.line_pad(self.line_pad)
|
||||
.window_controls(!self.no_window_controls)
|
||||
|
|
|
@ -148,6 +148,7 @@ fn run() -> Result<(), Error> {
|
|||
let mut formatter = config.get_formatter()?;
|
||||
|
||||
let image = formatter.format(&highlight, &theme);
|
||||
let image = DynamicImage::ImageRgba8(image);
|
||||
|
||||
if config.to_clipboard {
|
||||
dump_image_to_clipboard(&image)?;
|
||||
|
|
61
src/font.rs
61
src/font.rs
|
@ -21,7 +21,7 @@ use font_kit::font::Font;
|
|||
use font_kit::hinting::HintingOptions;
|
||||
use font_kit::properties::{Properties, Style, Weight};
|
||||
use font_kit::source::SystemSource;
|
||||
use image::{GenericImage, Pixel};
|
||||
use image::{GenericImage, Pixel, Rgba, RgbaImage};
|
||||
use imageproc::definitions::Clamp;
|
||||
use imageproc::pixelops::weighted_sum;
|
||||
use pathfinder_geometry::transform2d::Transform2F;
|
||||
|
@ -29,6 +29,46 @@ use std::collections::HashMap;
|
|||
use std::sync::Arc;
|
||||
use syntect::highlighting;
|
||||
|
||||
/// a single line text drawer
|
||||
pub trait TextLineDrawer {
|
||||
/// get the height of the text
|
||||
fn height(&mut self, text: &str) -> u32;
|
||||
/// get the width of the text
|
||||
fn width(&mut self, text: &str) -> u32;
|
||||
/// draw the text
|
||||
fn draw_text(
|
||||
&mut self,
|
||||
image: &mut RgbaImage,
|
||||
color: Rgba<u8>,
|
||||
x: u32,
|
||||
y: u32,
|
||||
font_style: FontStyle,
|
||||
text: &str,
|
||||
);
|
||||
}
|
||||
|
||||
impl TextLineDrawer for FontCollection {
|
||||
fn height(&mut self, _text: &str) -> u32 {
|
||||
self.get_font_height()
|
||||
}
|
||||
|
||||
fn width(&mut self, text: &str) -> u32 {
|
||||
self.layout(text, REGULAR).1
|
||||
}
|
||||
|
||||
fn draw_text(
|
||||
&mut self,
|
||||
image: &mut RgbaImage,
|
||||
color: Rgba<u8>,
|
||||
x: u32,
|
||||
y: u32,
|
||||
font_style: FontStyle,
|
||||
text: &str,
|
||||
) {
|
||||
self.draw_text_mut(image, color, x, y, font_style, text);
|
||||
}
|
||||
}
|
||||
|
||||
/// Font style
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum FontStyle {
|
||||
|
@ -172,11 +212,15 @@ impl ImageFont {
|
|||
///
|
||||
/// It can be used to draw text on the image.
|
||||
#[derive(Debug)]
|
||||
pub struct FontCollection(Vec<ImageFont>);
|
||||
pub struct FontCollection {
|
||||
fonts: Vec<ImageFont>,
|
||||
}
|
||||
|
||||
impl Default for FontCollection {
|
||||
fn default() -> Self {
|
||||
Self(vec![ImageFont::default()])
|
||||
Self {
|
||||
fonts: vec![ImageFont::default()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,11 +235,11 @@ impl FontCollection {
|
|||
Err(err) => eprintln!("[error] Error occurs when load font `{}`: {}", name, err),
|
||||
}
|
||||
}
|
||||
Ok(Self(fonts))
|
||||
Ok(Self { fonts })
|
||||
}
|
||||
|
||||
fn glyph_for_char(&self, c: char, style: FontStyle) -> Option<(u32, &ImageFont, &Font)> {
|
||||
for font in &self.0 {
|
||||
for font in &self.fonts {
|
||||
let result = font.get_by_style(style);
|
||||
if let Some(id) = result.glyph_for_char(c) {
|
||||
return Some((id, font, result));
|
||||
|
@ -207,7 +251,7 @@ impl FontCollection {
|
|||
|
||||
/// get max height of all the fonts
|
||||
pub fn get_font_height(&self) -> u32 {
|
||||
self.0
|
||||
self.fonts
|
||||
.iter()
|
||||
.map(|font| font.get_font_height())
|
||||
.max()
|
||||
|
@ -350,9 +394,9 @@ impl FontCollection {
|
|||
I: GenericImage,
|
||||
<I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
|
||||
{
|
||||
let metrics = self.0[0].get_regular().metrics();
|
||||
let metrics = self.fonts[0].get_regular().metrics();
|
||||
let offset =
|
||||
(metrics.descent / metrics.units_per_em as f32 * self.0[0].size).round() as i32;
|
||||
(metrics.descent / metrics.units_per_em as f32 * self.fonts[0].size).round() as i32;
|
||||
|
||||
let (glyphs, width) = self.layout(text, style);
|
||||
|
||||
|
@ -372,6 +416,7 @@ impl FontCollection {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PositionedGlyph {
|
||||
id: u32,
|
||||
font: Font,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//! Format the output of syntect into an image
|
||||
use crate::error::FontError;
|
||||
use crate::font::{FontCollection, FontStyle};
|
||||
use crate::font::{FontCollection, FontStyle, TextLineDrawer};
|
||||
use crate::utils::*;
|
||||
use image::{DynamicImage, GenericImageView, Rgba, RgbaImage};
|
||||
use image::{Rgba, RgbaImage};
|
||||
use syntect::highlighting::{Color, Style, Theme};
|
||||
|
||||
pub struct ImageFormatter {
|
||||
pub struct ImageFormatter<T> {
|
||||
/// pad between lines
|
||||
/// Default: 2
|
||||
line_pad: u32,
|
||||
|
@ -42,7 +42,7 @@ pub struct ImageFormatter {
|
|||
line_number_chars: u32,
|
||||
/// font of english character, should be mono space font
|
||||
/// Default: Hack (builtin)
|
||||
font: FontCollection,
|
||||
font: T,
|
||||
/// Highlight lines
|
||||
highlight_lines: Vec<u32>,
|
||||
/// Shadow adder
|
||||
|
@ -151,7 +151,7 @@ impl<S: AsRef<str> + Default> ImageFormatterBuilder<S> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<ImageFormatter, FontError> {
|
||||
pub fn build(self) -> Result<ImageFormatter<FontCollection>, FontError> {
|
||||
let font = if self.font.is_empty() {
|
||||
FontCollection::default()
|
||||
} else {
|
||||
|
@ -191,19 +191,19 @@ struct Drawable {
|
|||
drawables: Vec<(u32, u32, Option<Color>, FontStyle, String)>,
|
||||
}
|
||||
|
||||
impl ImageFormatter {
|
||||
impl<T: TextLineDrawer> ImageFormatter<T> {
|
||||
/// calculate the height of a line
|
||||
fn get_line_height(&self) -> u32 {
|
||||
self.font.get_font_height() + self.line_pad
|
||||
fn get_line_height(&mut self) -> u32 {
|
||||
self.font.height(" ") + self.line_pad
|
||||
}
|
||||
|
||||
/// calculate the Y coordinate of a line
|
||||
fn get_line_y(&self, lineno: u32) -> u32 {
|
||||
fn get_line_y(&mut self, lineno: u32) -> u32 {
|
||||
lineno * self.get_line_height() + self.code_pad + self.code_pad_top
|
||||
}
|
||||
|
||||
/// calculate the size of code area
|
||||
fn get_image_size(&self, max_width: u32, lineno: u32) -> (u32, u32) {
|
||||
fn get_image_size(&mut self, max_width: u32, lineno: u32) -> (u32, u32) {
|
||||
(
|
||||
(max_width + self.code_pad).max(150),
|
||||
self.get_line_y(lineno + 1) + self.code_pad,
|
||||
|
@ -211,18 +211,18 @@ impl ImageFormatter {
|
|||
}
|
||||
|
||||
/// Calculate where code start
|
||||
fn get_left_pad(&self) -> u32 {
|
||||
fn get_left_pad(&mut self) -> u32 {
|
||||
self.code_pad
|
||||
+ if self.line_number {
|
||||
let tmp = format!("{:>width$}", 0, width = self.line_number_chars as usize);
|
||||
2 * self.line_number_pad + self.font.get_text_len(&tmp)
|
||||
2 * self.line_number_pad + self.font.width(&tmp)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// create
|
||||
fn create_drawables(&self, v: &[Vec<(Style, &str)>]) -> Drawable {
|
||||
fn create_drawables(&mut self, v: &[Vec<(Style, &str)>]) -> Drawable {
|
||||
// tab should be replaced to whitespace so that it can be rendered correctly
|
||||
let tab = " ".repeat(self.tab_width as usize);
|
||||
let mut drawables = vec![];
|
||||
|
@ -246,7 +246,7 @@ impl ImageFormatter {
|
|||
text.to_owned(),
|
||||
));
|
||||
|
||||
width += self.font.get_text_len(&text);
|
||||
width += self.font.width(&text);
|
||||
|
||||
max_width = max_width.max(width);
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ impl ImageFormatter {
|
|||
|
||||
if self.window_title.is_some() {
|
||||
let title = self.window_title.as_ref().unwrap();
|
||||
let title_width = self.font.get_text_len(title);
|
||||
let title_width = self.font.width(title);
|
||||
|
||||
let ctrls_offset = if self.window_controls {
|
||||
self.window_controls_width + self.title_bar_pad
|
||||
|
@ -266,7 +266,7 @@ impl ImageFormatter {
|
|||
|
||||
drawables.push((
|
||||
ctrls_offset + self.title_bar_pad,
|
||||
self.title_bar_pad + ctrls_center - self.font.get_font_height() / 2,
|
||||
self.title_bar_pad + ctrls_center - self.font.height(" ") / 2,
|
||||
None,
|
||||
FontStyle::BOLD,
|
||||
title.to_string(),
|
||||
|
@ -283,7 +283,7 @@ impl ImageFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_line_number(&self, image: &mut DynamicImage, lineno: u32, mut color: Rgba<u8>) {
|
||||
fn draw_line_number(&mut self, image: &mut RgbaImage, lineno: u32, mut color: Rgba<u8>) {
|
||||
for i in color.0.iter_mut() {
|
||||
*i = (*i).saturating_sub(20);
|
||||
}
|
||||
|
@ -293,36 +293,37 @@ impl ImageFormatter {
|
|||
i + self.line_offset,
|
||||
width = self.line_number_chars as usize
|
||||
);
|
||||
self.font.draw_text_mut(
|
||||
let y = self.get_line_y(i);
|
||||
self.font.draw_text(
|
||||
image,
|
||||
color,
|
||||
self.code_pad,
|
||||
self.get_line_y(i),
|
||||
y,
|
||||
FontStyle::REGULAR,
|
||||
&line_number,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn highlight_lines<I: IntoIterator<Item = u32>>(&self, image: &mut DynamicImage, lines: I) {
|
||||
fn highlight_lines<I: IntoIterator<Item = u32>>(&mut self, image: &mut RgbaImage, lines: I) {
|
||||
let width = image.width();
|
||||
let height = self.font.get_font_height() + self.line_pad;
|
||||
let mut color = image.get_pixel(20, 20);
|
||||
let height = self.get_line_height();
|
||||
let color = image.get_pixel_mut(20, 20);
|
||||
|
||||
for i in color.0.iter_mut() {
|
||||
*i = (*i).saturating_add(40);
|
||||
}
|
||||
|
||||
let shadow = RgbaImage::from_pixel(width, height, color);
|
||||
let shadow = RgbaImage::from_pixel(width, height, *color);
|
||||
|
||||
for i in lines {
|
||||
let y = self.get_line_y(i - 1);
|
||||
copy_alpha(&shadow, image.as_mut_rgba8().unwrap(), 0, y);
|
||||
copy_alpha(&shadow, image, 0, y);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use &T instead of &mut T ?
|
||||
pub fn format(&mut self, v: &[Vec<(Style, &str)>], theme: &Theme) -> DynamicImage {
|
||||
pub fn format(&mut self, v: &[Vec<(Style, &str)>], theme: &Theme) -> RgbaImage {
|
||||
if self.line_number {
|
||||
self.line_number_chars =
|
||||
(((v.len() + self.line_offset as usize) as f32).log10() + 1.0).floor() as u32;
|
||||
|
@ -338,15 +339,15 @@ impl ImageFormatter {
|
|||
let foreground = theme.settings.foreground.unwrap();
|
||||
let background = theme.settings.background.unwrap();
|
||||
|
||||
let mut image =
|
||||
DynamicImage::ImageRgba8(RgbaImage::from_pixel(size.0, size.1, background.to_rgba()));
|
||||
let mut image = RgbaImage::from_pixel(size.0, size.1, background.to_rgba());
|
||||
|
||||
if !self.highlight_lines.is_empty() {
|
||||
let highlight_lines = self
|
||||
.highlight_lines
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|&n| n >= 1 && n <= drawables.max_lineno + 1);
|
||||
.filter(|&n| n >= 1 && n <= drawables.max_lineno + 1)
|
||||
.collect::<Vec<_>>();
|
||||
self.highlight_lines(&mut image, highlight_lines);
|
||||
}
|
||||
if self.line_number {
|
||||
|
@ -355,8 +356,7 @@ impl ImageFormatter {
|
|||
|
||||
for (x, y, color, style, text) in drawables.drawables {
|
||||
let color = color.unwrap_or(foreground).to_rgba();
|
||||
self.font
|
||||
.draw_text_mut(&mut image, color, x, y, style, &text);
|
||||
self.font.draw_text(&mut image, color, x, y, style, &text);
|
||||
}
|
||||
|
||||
if self.window_controls {
|
||||
|
|
30
src/utils.rs
30
src/utils.rs
|
@ -1,7 +1,7 @@
|
|||
use crate::error::ParseColorError;
|
||||
use image::imageops::{crop_imm, resize, FilterType};
|
||||
use image::Pixel;
|
||||
use image::{DynamicImage, GenericImage, GenericImageView, Rgba, RgbaImage};
|
||||
use image::{GenericImage, GenericImageView, Rgba, RgbaImage};
|
||||
use imageproc::drawing::{draw_filled_rect_mut, draw_line_segment_mut};
|
||||
use imageproc::rect::Rect;
|
||||
|
||||
|
@ -74,17 +74,17 @@ pub struct WindowControlsParams {
|
|||
}
|
||||
|
||||
/// Add the window controls for image
|
||||
pub(crate) fn add_window_controls(image: &mut DynamicImage, params: &WindowControlsParams) {
|
||||
pub(crate) fn add_window_controls(image: &mut RgbaImage, params: &WindowControlsParams) {
|
||||
let color = [
|
||||
("#FF5F56", "#E0443E"),
|
||||
("#FFBD2E", "#DEA123"),
|
||||
("#27C93F", "#1AAB29"),
|
||||
];
|
||||
|
||||
let mut background = image.get_pixel(37, 37);
|
||||
let background = image.get_pixel_mut(37, 37);
|
||||
background.0[3] = 0;
|
||||
|
||||
let mut title_bar = RgbaImage::from_pixel(params.width * 3, params.height * 3, background);
|
||||
let mut title_bar = RgbaImage::from_pixel(params.width * 3, params.height * 3, *background);
|
||||
let step = (params.radius * 2) as i32;
|
||||
let spacer = step * 2;
|
||||
let center_y = (params.height / 2) as i32;
|
||||
|
@ -112,12 +112,7 @@ pub(crate) fn add_window_controls(image: &mut DynamicImage, params: &WindowContr
|
|||
FilterType::Triangle,
|
||||
);
|
||||
|
||||
copy_alpha(
|
||||
&title_bar,
|
||||
image.as_mut_rgba8().unwrap(),
|
||||
params.padding,
|
||||
params.padding,
|
||||
);
|
||||
copy_alpha(&title_bar, image, params.padding, params.padding);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -204,7 +199,7 @@ impl ShadowAdder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn apply_to(&self, image: &DynamicImage) -> DynamicImage {
|
||||
pub fn apply_to(&self, image: &RgbaImage) -> RgbaImage {
|
||||
// the size of the final image
|
||||
let width = image.width() + self.pad_horiz * 2;
|
||||
let height = image.height() + self.pad_vert * 2;
|
||||
|
@ -226,14 +221,9 @@ impl ShadowAdder {
|
|||
// shadow = blur(&shadow, self.blur_radius);
|
||||
|
||||
// copy the original image to the top of it
|
||||
copy_alpha(
|
||||
image.as_rgba8().unwrap(),
|
||||
&mut shadow,
|
||||
self.pad_horiz,
|
||||
self.pad_vert,
|
||||
);
|
||||
copy_alpha(image, &mut shadow, self.pad_horiz, self.pad_vert);
|
||||
|
||||
DynamicImage::ImageRgba8(shadow)
|
||||
shadow
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,7 +256,7 @@ pub(crate) fn copy_alpha(src: &RgbaImage, dst: &mut RgbaImage, x: u32, y: u32) {
|
|||
}
|
||||
|
||||
/// Round the corner of the image
|
||||
pub(crate) fn round_corner(image: &mut DynamicImage, radius: u32) {
|
||||
pub(crate) fn round_corner(image: &mut RgbaImage, radius: u32) {
|
||||
// draw a circle with given foreground on given background
|
||||
// then split it into four pieces and paste them to the four corner of the image
|
||||
//
|
||||
|
@ -287,7 +277,7 @@ pub(crate) fn round_corner(image: &mut DynamicImage, radius: u32) {
|
|||
&mut circle,
|
||||
(((radius + 1) * 2) as i32, ((radius + 1) * 2) as i32),
|
||||
radius as i32 * 2,
|
||||
foreground,
|
||||
*foreground,
|
||||
);
|
||||
|
||||
// scale down the circle to the correct size
|
||||
|
|
Loading…
Reference in New Issue