Skip to content

Commit

Permalink
feat: move window tab generation to lib
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioRibera committed Jan 11, 2024
1 parent 0df37bc commit 68c7602
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 143 deletions.
64 changes: 60 additions & 4 deletions crates/sss_cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::path::PathBuf;

use clap::Parser;
use sss_lib::error::FontError;
use sss_lib::font::FontCollection;
use sss_lib::image::{
error::{ImageFormatHint, UnsupportedError, UnsupportedErrorKind},
ImageError, ImageFormat,
Expand All @@ -25,6 +27,8 @@ pub struct CliConfig {
#[clap(long, help = "Captures an area of the screen", value_parser = str_to_area)]
pub area: Option<(i32, i32, u32, u32)>,
// Screenshot Section
#[clap(long, default_value = "Hack=12.0;", help = "[default: Hack=12.0;] The font used to render, format: Font Name=size;Other Font Name=12.0", value_parser = parse_font_str)]
pub font: FontCollection,
#[clap(
long,
short,
Expand All @@ -34,6 +38,31 @@ pub struct CliConfig {
pub background: String,
#[clap(long, short, default_value = "15")]
pub radius: u32,
#[clap(long, help = "Author Name of screenshot")]
pub author: Option<String>,
#[clap(long, default_value = "#FFFFFF", help = "Title bar text color")]
pub author_color: String,
#[clap(long, default_value = "Hack", help = "Font to render Author")]
pub author_font: String,
// Window Bar
#[clap(long, help = "Whether show the window controls")]
pub window_controls: bool,
#[clap(long, help = "Window title")]
pub window_title: Option<String>,
#[clap(long, default_value = "#4287f5", help = "Window bar background")]
pub windows_background: String,
#[clap(long, default_value = "#FFFFFF", help = "Title bar text color")]
pub windows_title_color: String,
#[clap(long, default_value = "120", help = "Width of window controls")]
pub window_controls_width: u32,
#[clap(
long,
default_value = "40",
help = "Height of window title/controls bar"
)]
pub window_controls_height: u32,
#[clap(long, default_value = "10", help = "Padding of title on window bar")]
pub titlebar_padding: u32,
// Padding Section
#[clap(long, default_value = "80")]
pub padding_x: u32,
Expand All @@ -51,7 +80,7 @@ pub struct CliConfig {
#[clap(
long,
default_value = "#707070",
help = "Support: '#RRGGBBAA' '#RRGGBBAA;#RRGGBBAA' or file path"
help = "Support: '#RRGGBBAA' 'h;#RRGGBBAA;#RRGGBBAA' 'v;#RRGGBBAA;#RRGGBBAA' or file path"
)]
pub shadow_color: String,
#[clap(long, default_value = "50")]
Expand Down Expand Up @@ -82,16 +111,29 @@ pub fn get_config() -> CliConfig {
impl From<CliConfig> for GenerationSettings {
fn from(val: CliConfig) -> Self {
let background = Background::try_from(val.background.clone()).unwrap();
let windows_background = Background::try_from(val.windows_background.clone()).unwrap();
let shadow_color = Background::try_from(val.shadow_color.clone()).unwrap();

GenerationSettings {
background: background.clone(),
windows_background,
background,
padding: (val.padding_x, val.padding_y),
round_corner: Some(val.radius),
shadow: val.shadow.then_some(Shadow {
background,
shadow_color,
use_inner_image: val.shadow_image,
shadow_color: val.shadow_color.to_rgba().unwrap(),
blur_radius: val.shadow_blur,
}),
fonts: val.font,
author: val.author.clone(),
author_font: val.author_font.clone(),
author_color: val.author_color.to_rgba().unwrap(),
window_controls: val.window_controls,
windows_title: val.window_title.clone(),
windows_title_color: val.windows_title_color.to_rgba().unwrap(),
window_controls_width: val.window_controls_width,
window_controls_height: val.window_controls_height,
titlebar_padding: val.titlebar_padding,
}
}
}
Expand All @@ -105,6 +147,20 @@ fn str_to_format(s: &str) -> Result<ImageFormat, ImageError> {
))
}

fn parse_font_str(s: &str) -> Result<FontCollection, FontError> {
let fonts = s
.split(';')
.filter_map(|f| {
(!f.is_empty()).then(|| {
let (name, size) = f.split_once('=').unwrap();
(name.to_owned(), size.parse::<f32>().unwrap_or(26.))
})
})
.collect::<Vec<(String, f32)>>();

FontCollection::new(&fonts)
}

fn str_to_area(s: &str) -> Result<(i32, i32, u32, u32), String> {
let err = "The format of area is wrong (x,y WxH)".to_string();
let (pos, size) = s.split_once(" ").ok_or(err.clone())?;
Expand Down
4 changes: 2 additions & 2 deletions crates/sss_cli/src/img.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Screenshot {
impl Screenshot {}

impl DynImageContent for Screenshot {
fn content(&self) -> sss_lib::image::DynamicImage {
fn content(&self) -> sss_lib::image::RgbaImage {
let shot = ShotImpl::default();
let img = if self.config.screen && self.config.current {
screenshots::Screen::from_point(0, 0) // replace by mouse
Expand All @@ -23,6 +23,6 @@ impl DynImageContent for Screenshot {
shot.all(self.config.show_cursor).unwrap()
};

sss_lib::image::DynamicImage::ImageRgba8(img)
img
}
}
65 changes: 52 additions & 13 deletions crates/sss_code/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use std::path::PathBuf;

use clap::Parser;
use clap_stdin::FileOrStdin;
use sss_lib::error::FontError;
use sss_lib::font::FontCollection;
use sss_lib::image::error::{ImageFormatHint, UnsupportedError, UnsupportedErrorKind};
use sss_lib::image::{ImageError, ImageFormat};
use sss_lib::{Background, GenerationSettings, Shadow, ToRgba};

use crate::error::CodeScreenshotError;

pub type FontList = Vec<(String, f32)>;

#[derive(Clone, Parser)]
#[clap(author, version, about)]
pub struct CodeConfig {
Expand All @@ -23,8 +23,8 @@ pub struct CodeConfig {
help = "Theme file to use. May be a path, or an embedded theme. Embedded themes will take precendence."
)]
pub theme: String,
#[clap(long, help = "[default: Hack=26.0;] The font used to render, format: Font Name=size;Other Font Name=12.0", value_parser = parse_font_str)]
pub font: Option<FontList>,
#[clap(long, default_value = "Hack=12.0;", help = "[default: Hack=12.0;] The font used to render, format: Font Name=size;Other Font Name=12.0", value_parser = parse_font_str)]
pub font: FontCollection,
#[clap(
long,
help = "[Not recommended for manual use] Set theme from vim highlights, format: group,bg,fg,style;group,bg,fg,style;"
Expand All @@ -51,10 +51,31 @@ pub struct CodeConfig {
pub line_numbers: bool,
#[clap(long, default_value = "4", help = "Tab width")]
pub tab_width: u8,
#[clap(long, help = "Author Name of screenshot")]
pub author: Option<String>,
#[clap(long, default_value = "#FFFFFF", help = "Title bar text color")]
pub author_color: String,
#[clap(long, default_value = "Hack", help = "Font to render Author")]
pub author_font: String,
// Window Bar
#[clap(long, help = "Whether show the window controls")]
pub window_controls: bool,
#[clap(long, help = "Window title")]
pub window_title: Option<String>,
#[clap(long, default_value = "#4287f5", help = "Window bar background")]
pub windows_background: String,
#[clap(long, default_value = "#FFFFFF", help = "Title bar text color")]
pub windows_title_color: String,
#[clap(long, default_value = "120", help = "Width of window controls")]
pub window_controls_width: u32,
#[clap(
long,
default_value = "40",
help = "Height of window title/controls bar"
)]
pub window_controls_height: u32,
#[clap(long, default_value = "10", help = "Padding of title on window bar")]
pub titlebar_padding: u32,
// Screenshot Section
#[clap(
long,
Expand All @@ -78,7 +99,7 @@ pub struct CodeConfig {
#[clap(
long,
default_value = "#707070",
help = "Support: '#RRGGBBAA' '#RRGGBBAA;#RRGGBBAA' or file path"
help = "Support: '#RRGGBBAA' 'h;#RRGGBBAA;#RRGGBBAA' 'v;#RRGGBBAA;#RRGGBBAA' or file path"
)]
pub shadow_color: String,
#[clap(long, default_value = "50")]
Expand Down Expand Up @@ -109,16 +130,29 @@ pub fn get_config() -> CodeConfig {
impl From<CodeConfig> for GenerationSettings {
fn from(val: CodeConfig) -> Self {
let background = Background::try_from(val.background.clone()).unwrap();
let windows_background = Background::try_from(val.windows_background.clone()).unwrap();
let shadow_color = Background::try_from(val.shadow_color.clone()).unwrap();

GenerationSettings {
windows_background,
background: background.clone(),
padding: (val.padding_x, val.padding_y),
round_corner: Some(val.radius),
shadow: val.shadow.then_some(Shadow {
background,
shadow_color,
use_inner_image: val.shadow_image,
shadow_color: val.shadow_color.to_rgba().unwrap(),
blur_radius: val.shadow_blur,
}),
fonts: val.font,
author: val.author.clone(),
author_font: val.author_font.clone(),
author_color: val.author_color.to_rgba().unwrap(),
window_controls: val.window_controls,
windows_title: val.window_title.clone(),
windows_title_color: val.windows_title_color.to_rgba().unwrap(),
window_controls_width: val.window_controls_width,
window_controls_height: val.window_controls_height,
titlebar_padding: val.titlebar_padding,
}
}
}
Expand Down Expand Up @@ -157,11 +191,16 @@ fn str_to_format(s: &str) -> Result<ImageFormat, ImageError> {
))
}

fn parse_font_str(s: &str) -> Result<Vec<(String, f32)>, String> {
Ok(s.split(';')
.map(|font| {
let (name, size) = font.split_once('=').unwrap();
(name.to_owned(), size.parse::<f32>().unwrap_or(26.))
fn parse_font_str(s: &str) -> Result<FontCollection, FontError> {
let fonts = s
.split(';')
.filter_map(|f| {
(!f.is_empty()).then(|| {
let (name, size) = f.split_once('=').unwrap();
(name.to_owned(), size.parse::<f32>().unwrap_or(26.))
})
})
.collect::<Vec<(String, f32)>>())
.collect::<Vec<(String, f32)>>();

FontCollection::new(&fonts)
}
45 changes: 7 additions & 38 deletions crates/sss_code/src/img.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@
use std::borrow::Cow;
use std::ops::Range;

use sss_lib::image::{DynamicImage, Rgba, RgbaImage};
use sss_lib::font::{FontCollection, FontStyle};
use sss_lib::image::{Rgba, RgbaImage};
use sss_lib::DynImageContent;
use syntect::easy::HighlightLines;
use syntect::highlighting::{Color, Style, Theme};
use syntect::parsing::{SyntaxReference, SyntaxSet};

use crate::config::CodeConfig;
use crate::utils::{add_window_controls, color_to_rgba, fontstyle_from_syntect};
use crate::utils::{color_to_rgba, fontstyle_from_syntect};

type Drawable = (u32, u32, Option<Color>, FontStyle, String);

const LINE_SPACE: u32 = 5;
const LINE_NUMBER_RIGHT: u32 = 7;
const TITLE_BAR_PADDING: u32 = 10;
const WINDOW_CONTROLS_WIDTH: u32 = 120;
const WINDOW_CONTROLS_HEIGHT: u32 = 40;

const CODE_PADDING: u32 = 25;

Expand All @@ -45,7 +42,7 @@ impl<'a> ImageCode<'a> {
lineno * self.get_line_height()
+ CODE_PADDING
+ if self.config.window_controls || self.config.window_title.is_some() {
WINDOW_CONTROLS_HEIGHT + TITLE_BAR_PADDING
self.config.window_controls_height + self.config.titlebar_padding
} else {
0
}
Expand Down Expand Up @@ -103,7 +100,7 @@ impl<'a> ImageCode<'a> {

fn draw_line_number(
&self,
img: &mut DynamicImage,
img: &mut RgbaImage,
lines: Range<usize>,
line_hi: Range<usize>,
lineno: u32,
Expand Down Expand Up @@ -140,7 +137,7 @@ impl<'a> ImageCode<'a> {
}

impl<'a> DynImageContent for ImageCode<'a> {
fn content(&self) -> DynamicImage {
fn content(&self) -> RgbaImage{
let mut h = HighlightLines::new(self.syntax, &self.theme);
let mut drawables = Vec::new();
let mut max_width = 0;
Expand Down Expand Up @@ -174,23 +171,6 @@ impl<'a> DynImageContent for ImageCode<'a> {
.unwrap_or_default();
let max_lineno = line_range.len() as u32;

if let Some(title) = self.config.window_title.as_ref() {
let title_width = self.font.get_text_len(title);
drawables.push((
TITLE_BAR_PADDING
+ if self.config.window_controls {
WINDOW_CONTROLS_WIDTH + TITLE_BAR_PADDING
} else {
self.get_left_pad(max_lineno) + TITLE_BAR_PADDING
},
TITLE_BAR_PADDING + (WINDOW_CONTROLS_HEIGHT / 2) - self.font.get_font_height() / 2,
None,
FontStyle::Bold,
title.to_string(),
));
max_width = max_width.max(WINDOW_CONTROLS_WIDTH + title_width + TITLE_BAR_PADDING * 2)
}

for (n, line) in lines[line_range.clone()].iter().enumerate() {
let line = h.highlight_line(line, self.syntax_set).unwrap();
let hi = line_hi.contains(&(line_range.start + n));
Expand All @@ -208,11 +188,11 @@ impl<'a> DynImageContent for ImageCode<'a> {
self.get_line_y(max_lineno) + CODE_PADDING,
);

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

// Draw line numbers
if self.config.line_numbers {
Expand All @@ -232,17 +212,6 @@ impl<'a> DynImageContent for ImageCode<'a> {
.draw_text_mut(&mut img, color, *x, *y, *style, text);
}

// Draw window controlls
if self.config.window_controls {
add_window_controls(
&mut img,
WINDOW_CONTROLS_WIDTH,
WINDOW_CONTROLS_HEIGHT,
TITLE_BAR_PADDING,
WINDOW_CONTROLS_WIDTH / 3 / 4,
);
}

img
}
}
7 changes: 1 addition & 6 deletions crates/sss_code/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::borrow::Cow;

use config::get_config;
use img::ImageCode;
use sss_lib::font::FontCollection;
use sss_lib::generate_image;
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
Expand Down Expand Up @@ -57,11 +56,7 @@ fn main() {
let out = generate_image(
config.clone().into(),
ImageCode {
font: config
.font
.as_ref()
.and_then(|f| FontCollection::new(f).ok())
.unwrap_or_default(),
font: config.font.clone(),
config: config.clone(),
syntax,
theme,
Expand Down
Loading

0 comments on commit 68c7602

Please sign in to comment.