Skip to content

Commit

Permalink
feat: Option to show a custom window title (Aloxaf#215)
Browse files Browse the repository at this point in the history
closes Aloxaf#180
  • Loading branch information
mrcoalp authored Nov 14, 2022
1 parent 21d9447 commit 4d15f35
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 22 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ The color can be `#RGB[A]` or `#RRGGBB[AA]`
silicon ./target/test.rs -o test.png --background '#fff0'
```

Show window title

```bash
silicon ./target/test.rs -o test.png --window-title "target/test.rs"
```

see `silicon --help` for detail

## Adding new syntaxes / themes
Expand Down
6 changes: 5 additions & 1 deletion src/bin/silicon/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ pub struct Config {
#[structopt(long)]
pub no_window_controls: bool,

/// Show window title
#[structopt(long, value_name = "WINDOW_TITLE")]
pub window_title: Option<String>,

/// Hide the line number.
#[structopt(long)]
pub no_line_number: bool,
Expand Down Expand Up @@ -269,10 +273,10 @@ impl Config {
let formatter = ImageFormatterBuilder::new()
.line_pad(self.line_pad)
.window_controls(!self.no_window_controls)
.window_title(self.window_title.clone())
.line_number(!self.no_line_number)
.font(self.font.clone().unwrap_or_default())
.round_corner(!self.no_round_corner)
.window_controls(!self.no_window_controls)
.shadow_adder(self.get_shadow_adder()?)
.tab_width(self.tab_width)
.highlight_lines(self.highlight_lines.clone().unwrap_or_default())
Expand Down
79 changes: 66 additions & 13 deletions src/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ pub struct ImageFormatter {
/// pad of top of the code area
/// Default: 50
code_pad_top: u32,
/// Title bar padding
/// Default: 15
title_bar_pad: u32,
/// Whether to show window controls or not
window_controls: bool,
/// Width for window controls
/// Default: 120
window_controls_width: u32,
/// Height for window controls
/// Default: 40
window_controls_height: u32,
/// Window title
window_title: Option<String>,
/// show line number
/// Default: true
line_number: bool,
Expand Down Expand Up @@ -52,6 +65,8 @@ pub struct ImageFormatterBuilder<S> {
highlight_lines: Vec<u32>,
/// Whether show the window controls
window_controls: bool,
/// Window title
window_title: Option<String>,
/// Whether round the corner of the image
round_corner: bool,
/// Shadow adder,
Expand All @@ -69,6 +84,7 @@ impl<S: AsRef<str> + Default> ImageFormatterBuilder<S> {
line_pad: 2,
line_number: true,
window_controls: true,
window_title: None,
round_corner: true,
tab_width: 4,
..Default::default()
Expand Down Expand Up @@ -105,6 +121,12 @@ impl<S: AsRef<str> + Default> ImageFormatterBuilder<S> {
self
}

/// Window title
pub fn window_title(mut self, title: Option<String>) -> Self {
self.window_title = title;
self
}

/// Whether round the corner
pub fn round_corner(mut self, b: bool) -> Self {
self.round_corner = b;
Expand Down Expand Up @@ -136,19 +158,24 @@ impl<S: AsRef<str> + Default> ImageFormatterBuilder<S> {
FontCollection::new(&self.font)?
};

let code_pad_top = if self.window_controls { 50 } else { 0 };
let title_bar = self.window_controls || self.window_title.is_some();

Ok(ImageFormatter {
line_pad: self.line_pad,
code_pad: 25,
code_pad_top: if title_bar { 50 } else { 0 },
title_bar_pad: 15,
window_controls: self.window_controls,
window_controls_width: 120,
window_controls_height: 40,
window_title: self.window_title,
line_number: self.line_number,
line_number_pad: 6,
line_number_chars: 0,
highlight_lines: self.highlight_lines,
round_corner: self.round_corner,
shadow_adder: self.shadow_adder,
tab_width: self.tab_width,
code_pad_top,
font,
line_offset: self.line_offset,
})
Expand All @@ -161,7 +188,7 @@ struct Drawable {
/// max number of line of the picture
max_lineno: u32,
/// arguments for draw_text_mut
drawables: Vec<(u32, u32, Color, FontStyle, String)>,
drawables: Vec<(u32, u32, Option<Color>, FontStyle, String)>,
}

impl ImageFormatter {
Expand Down Expand Up @@ -214,7 +241,7 @@ impl ImageFormatter {
drawables.push((
width,
height,
style.foreground,
Some(style.foreground),
style.font_style.into(),
text.to_owned(),
));
Expand All @@ -226,6 +253,29 @@ impl ImageFormatter {
max_lineno = i as u32;
}

if self.window_title.is_some() {
let title = self.window_title.as_ref().unwrap();
let title_width = self.font.get_text_len(title);

let ctrls_offset = if self.window_controls {
self.window_controls_width + self.title_bar_pad
} else {
0
};
let ctrls_center = self.window_controls_height / 2;

drawables.push((
ctrls_offset + self.title_bar_pad,
self.title_bar_pad + ctrls_center - self.font.get_font_height() / 2,
None,
FontStyle::BOLD,
title.to_string(),
));

let title_bar_width = ctrls_offset + title_width + self.title_bar_pad * 2;
max_width = max_width.max(title_bar_width);
}

Drawable {
max_width,
max_lineno,
Expand Down Expand Up @@ -288,10 +338,8 @@ impl ImageFormatter {
let foreground = theme.settings.foreground.unwrap();
let background = theme.settings.background.unwrap();

let foreground = foreground.to_rgba();
let background = background.to_rgba();

let mut image = DynamicImage::ImageRgba8(RgbaImage::from_pixel(size.0, size.1, background));
let mut image =
DynamicImage::ImageRgba8(RgbaImage::from_pixel(size.0, size.1, background.to_rgba()));

if !self.highlight_lines.is_empty() {
let highlight_lines = self
Expand All @@ -302,18 +350,23 @@ impl ImageFormatter {
self.highlight_lines(&mut image, highlight_lines);
}
if self.line_number {
self.draw_line_number(&mut image, drawables.max_lineno, foreground);
self.draw_line_number(&mut image, drawables.max_lineno, foreground.to_rgba());
}

for (x, y, color, style, text) in drawables.drawables {
let color = color.to_rgba();
let color = color.unwrap_or(foreground).to_rgba();
self.font
.draw_text_mut(&mut image, color, x, y, style, &text);
}

// draw_window_controls == true
if self.code_pad_top != 0 {
add_window_controls(&mut image);
if self.window_controls {
let params = WindowControlsParams {
width: self.window_controls_width,
height: self.window_controls_height,
padding: self.title_bar_pad,
radius: self.window_controls_width / 3 / 4,
};
add_window_controls(&mut image, &params);
}

if self.round_corner {
Expand Down
36 changes: 28 additions & 8 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,15 @@ impl ToRgba for syntect::highlighting::Color {
}
}

pub struct WindowControlsParams {
pub width: u32,
pub height: u32,
pub padding: u32,
pub radius: u32,
}

/// Add the window controls for image
pub(crate) fn add_window_controls(image: &mut DynamicImage) {
pub(crate) fn add_window_controls(image: &mut DynamicImage, params: &WindowControlsParams) {
let color = [
("#FF5F56", "#E0443E"),
("#FFBD2E", "#DEA123"),
Expand All @@ -77,27 +84,40 @@ pub(crate) fn add_window_controls(image: &mut DynamicImage) {
let mut background = image.get_pixel(37, 37);
background.0[3] = 0;

let mut title_bar = RgbaImage::from_pixel(120 * 3, 40 * 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) as i32;
let center_y = (params.height / 2) as i32;

for (i, (fill, outline)) in color.iter().enumerate() {
draw_filled_circle_mut(
&mut title_bar,
(((i * 40) as i32 + 20) * 3, 20 * 3),
11 * 3,
((i as i32 * spacer + step) * 3, center_y * 3),
(params.radius + 1) as i32 * 3,
outline.to_rgba().unwrap(),
);
draw_filled_circle_mut(
&mut title_bar,
(((i * 40) as i32 + 20) * 3, 20 * 3),
10 * 3,
((i as i32 * spacer + step) * 3, center_y * 3),
params.radius as i32 * 3,
fill.to_rgba().unwrap(),
);
}
// create a big image and resize it to blur the edge
// it looks better than `blur()`
let title_bar = resize(&title_bar, 120, 40, FilterType::Triangle);
let title_bar = resize(
&title_bar,
params.width,
params.height,
FilterType::Triangle,
);

copy_alpha(&title_bar, image.as_mut_rgba8().unwrap(), 15, 15);
copy_alpha(
&title_bar,
image.as_mut_rgba8().unwrap(),
params.padding,
params.padding,
);
}

#[derive(Clone, Debug)]
Expand Down

0 comments on commit 4d15f35

Please sign in to comment.