mirror of https://github.com/Aloxaf/silicon
Compare commits
6 Commits
cf3668c9ee
...
cd1ec2f9f0
Author | SHA1 | Date |
---|---|---|
Aloxaf | cd1ec2f9f0 | |
Aloxaf | ba1ea1b5df | |
Aloxaf | 322db8f264 | |
Krapaince | 1f5f0e83e5 | |
LhAllant | 1a9077a742 | |
JScheffer | e195b5e0b0 |
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
16
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "silicon"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
description = "Create beautiful image of your code"
|
||||
authors = ["Aloxaf <aloxafx@gmail.com>"]
|
||||
categories = ["command-line-utilities"]
|
||||
|
@ -20,13 +20,13 @@ harfbuzz = ["harfbuzz-sys", "font-kit/loader-freetype-default", "font-kit/source
|
|||
dirs = "4.0"
|
||||
imageproc = "0.23.0"
|
||||
clipboard = "0.5.0"
|
||||
tempfile = "3.1.0"
|
||||
tempfile = "3.8.1"
|
||||
conv = "0.3.3"
|
||||
pathfinder_geometry = "0.5.1"
|
||||
log = "0.4.11"
|
||||
log = "0.4.20"
|
||||
lazy_static = "1.4.0"
|
||||
shell-words = { version = "1.0.0", optional = true }
|
||||
rayon = "1.5.1"
|
||||
shell-words = { version = "1.1.0", optional = true }
|
||||
rayon = "1.8.0"
|
||||
font-kit = "0.11"
|
||||
harfbuzz-sys = { version = "0.5.0", optional = true }
|
||||
|
||||
|
@ -36,7 +36,7 @@ default-features = false
|
|||
features = ["jpeg", "png", "jpeg_rayon"]
|
||||
|
||||
[dependencies.syntect]
|
||||
version = "5.0"
|
||||
version = "5.1"
|
||||
default-features = false
|
||||
features = ["parsing", "dump-load", "regex-onig", "plist-load", "yaml-load"]
|
||||
|
||||
|
@ -51,7 +51,7 @@ features = ["color", "wrap_help"]
|
|||
optional = true
|
||||
|
||||
[dependencies.env_logger]
|
||||
version = "0.9.1"
|
||||
version = "0.9.3"
|
||||
default-features = false
|
||||
features = ["termcolor", "atty", "humantime"]
|
||||
optional = true
|
||||
|
@ -60,7 +60,7 @@ optional = true
|
|||
pasteboard = "0.1.3"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
clipboard-win = "4.0.2"
|
||||
clipboard-win = "4.5.0"
|
||||
image = { version = "0.24", default-features = false, features = ["jpeg", "bmp", "jpeg_rayon"] }
|
||||
|
||||
[patch.crates-io]
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019-2022 Aloxaf
|
||||
Copyright (c) 2019-2023 Aloxaf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -9,7 +9,7 @@ Silicon is an alternative to [Carbon](https://github.com/dawnlabs/carbon) implem
|
|||
|
||||
It can render your source code into a beautiful image.
|
||||
|
||||
<img width="66%" src="http://storage.aloxaf.cn/silicon.png?v=2">
|
||||
<img width="66%" src="example/example.png">
|
||||
|
||||
## Why Silicon
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
|
@ -0,0 +1,10 @@
|
|||
fn factorial(n: u64) -> u64 {
|
||||
match n {
|
||||
0 => 1,
|
||||
_ => n * factorial(n - 1),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("10! = {}", factorial(10));
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
silicon example.rs -o example.png
|
|
@ -14,6 +14,12 @@ pub struct HighlightingAssets {
|
|||
pub theme_set: ThemeSet,
|
||||
}
|
||||
|
||||
impl Default for HighlightingAssets {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl HighlightingAssets {
|
||||
pub fn new() -> Self {
|
||||
Self::from_dump_file().unwrap_or_else(|_| Self {
|
||||
|
|
|
@ -14,6 +14,7 @@ use {
|
|||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
use {image::ImageOutputFormat, pasteboard::Pasteboard};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use {image::ImageOutputFormat, std::process::Command};
|
||||
|
||||
|
@ -24,18 +25,43 @@ use silicon::directories::PROJECT_DIRS;
|
|||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn dump_image_to_clipboard(image: &DynamicImage) -> Result<(), Error> {
|
||||
let mut temp = tempfile::NamedTempFile::new()?;
|
||||
image.write_to(&mut temp, ImageOutputFormat::Png)?;
|
||||
Command::new("xclip")
|
||||
.args([
|
||||
"-sel",
|
||||
"clip",
|
||||
"-t",
|
||||
"image/png",
|
||||
temp.path().to_str().unwrap(),
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format_err!("Failed to copy image to clipboard: {}", e))?;
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
match std::env::var(r#"XDG_SESSION_TYPE"#).ok() {
|
||||
Some(x) if x == "wayland" => {
|
||||
let mut command = Command::new("wl-copy")
|
||||
.args(["--type", "image/png"])
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.spawn()?;
|
||||
|
||||
let mut cursor = Cursor::new(Vec::new());
|
||||
image.write_to(&mut cursor, ImageOutputFormat::Png)?;
|
||||
|
||||
{
|
||||
let stdin = command.stdin.as_mut().unwrap();
|
||||
stdin.write_all(cursor.get_ref())?;
|
||||
}
|
||||
|
||||
command
|
||||
.wait()
|
||||
.map_err(|e| format_err!("Failed to copy image to clipboard: {}", e))?;
|
||||
}
|
||||
_ => {
|
||||
let mut temp = tempfile::NamedTempFile::new()?;
|
||||
image.write_to(&mut temp, ImageOutputFormat::Png)?;
|
||||
|
||||
Command::new(r#"xclip"#)
|
||||
.args([
|
||||
"-sel",
|
||||
"clip",
|
||||
"-t",
|
||||
"image/png",
|
||||
temp.path().to_str().unwrap(),
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format_err!("Failed to copy image to clipboard: {} (Tip: do you have xclip installed ?)", e))?;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ pub fn gaussian_blur(image: RgbaImage, sigma: f32) -> RgbaImage {
|
|||
RgbaImage::from_raw(width, height, raw).unwrap()
|
||||
}
|
||||
|
||||
fn gaussian_blur_impl(data: &mut Vec<[u8; 4]>, width: usize, height: usize, blur_radius: f32) {
|
||||
fn gaussian_blur_impl(data: &mut [[u8; 4]], width: usize, height: usize, blur_radius: f32) {
|
||||
let bxs = create_box_gauss(blur_radius, 3);
|
||||
let mut backbuf = data.clone();
|
||||
let mut backbuf = data.to_vec();
|
||||
|
||||
box_blur(
|
||||
&mut backbuf,
|
||||
|
@ -103,8 +103,8 @@ fn create_box_gauss(sigma: f32, n: usize) -> Vec<i32> {
|
|||
/// Needs 2x the same image
|
||||
#[inline]
|
||||
fn box_blur(
|
||||
backbuf: &mut Vec<[u8; 4]>,
|
||||
frontbuf: &mut Vec<[u8; 4]>,
|
||||
backbuf: &mut [[u8; 4]],
|
||||
frontbuf: &mut [[u8; 4]],
|
||||
width: usize,
|
||||
height: usize,
|
||||
blur_radius: usize,
|
||||
|
|
33
src/utils.rs
33
src/utils.rs
|
@ -86,7 +86,7 @@ pub(crate) fn add_window_controls(image: &mut DynamicImage, params: &WindowContr
|
|||
|
||||
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) as i32;
|
||||
let spacer = step * 2;
|
||||
let center_y = (params.height / 2) as i32;
|
||||
|
||||
for (i, (fill, outline)) in color.iter().enumerate() {
|
||||
|
@ -269,31 +269,48 @@ pub(crate) fn copy_alpha(src: &RgbaImage, dst: &mut RgbaImage, x: u32, y: u32) {
|
|||
pub(crate) fn round_corner(image: &mut DynamicImage, 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
|
||||
//
|
||||
// the circle is drawn on a bigger image to avoid the aliasing
|
||||
// later it will be scaled to the correct size
|
||||
// we add +1 (to the radius) to make sure that there is also space for the border to mitigate artefacts when scaling
|
||||
// note that the +1 isn't added to the radius when drawing the circle
|
||||
let mut circle =
|
||||
RgbaImage::from_pixel(radius * 2 + 1, radius * 2 + 1, Rgba([255, 255, 255, 0]));
|
||||
RgbaImage::from_pixel((radius + 1) * 4, (radius + 1) * 4, Rgba([255, 255, 255, 0]));
|
||||
|
||||
let width = image.width();
|
||||
let height = image.height();
|
||||
|
||||
// use the bottom right pixel to get the color of the foreground
|
||||
let foreground = image.get_pixel(width - 1, height - 1);
|
||||
|
||||
// TODO: need a blur on edge
|
||||
draw_filled_circle_mut(
|
||||
&mut circle,
|
||||
(radius as i32, radius as i32),
|
||||
radius as i32,
|
||||
(((radius + 1) * 2) as i32, ((radius + 1) * 2) as i32),
|
||||
radius as i32 * 2,
|
||||
foreground,
|
||||
);
|
||||
|
||||
let part = crop_imm(&circle, 0, 0, radius, radius);
|
||||
// scale down the circle to the correct size
|
||||
let circle = resize(
|
||||
&circle,
|
||||
(radius + 1) * 2,
|
||||
(radius + 1) * 2,
|
||||
FilterType::Triangle,
|
||||
);
|
||||
|
||||
// top left
|
||||
let part = crop_imm(&circle, 1, 1, radius, radius);
|
||||
image.copy_from(&*part, 0, 0).unwrap();
|
||||
|
||||
let part = crop_imm(&circle, radius + 1, 0, radius, radius);
|
||||
// top right
|
||||
let part = crop_imm(&circle, radius + 1, 1, radius, radius - 1);
|
||||
image.copy_from(&*part, width - radius, 0).unwrap();
|
||||
|
||||
let part = crop_imm(&circle, 0, radius + 1, radius, radius);
|
||||
// bottom left
|
||||
let part = crop_imm(&circle, 1, radius + 1, radius, radius);
|
||||
image.copy_from(&*part, 0, height - radius).unwrap();
|
||||
|
||||
// bottom right
|
||||
let part = crop_imm(&circle, radius + 1, radius + 1, radius, radius);
|
||||
image
|
||||
.copy_from(&*part, width - radius, height - radius)
|
||||
|
|
Loading…
Reference in New Issue