From 2ed9199148d8242a189ecdb060b5733787f88ada Mon Sep 17 00:00:00 2001 From: Aloxaf Date: Fri, 14 Oct 2022 14:05:04 +0800 Subject: [PATCH] fix: windows build (#208) --- .github/workflows/ci.yml | 31 ++++++++++++++++++++++-- Cargo.toml | 32 ++++++++++++------------- src/bin/silicon/main.rs | 6 ++--- src/font.rs | 51 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 +++-- 5 files changed, 103 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 740505c..1fe77ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,8 +11,8 @@ env: jobs: - test: - name: Test + test-linux: + name: x86_64-unknown-linux-gnu runs-on: ubuntu-latest steps: - name: Checkout @@ -56,3 +56,30 @@ jobs: with: command: test args: -- --nocapture + + test-windows: + name: x86_64-pc-windows-msvc + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + + - name: Cargo check + uses: actions-rs/cargo@v1 + with: + command: check + + - name: Cargo test + uses: actions-rs/cargo@v1 + with: + command: test + args: -- --nocapture diff --git a/Cargo.toml b/Cargo.toml index bd6f74a..92cfd79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,12 @@ repository = "https://github.com/Aloxaf/silicon" license = "MIT" edition = "2018" +[features] +# fearures required for silicon as a application +# disable it when using as a library +default = ["bin"] +bin = ["structopt", "env_logger", "anyhow", "shell-words"] + [dependencies] dirs = "4.0" imageproc = "0.23.0" @@ -21,13 +27,6 @@ lazy_static = "1.4.0" shell-words = { version = "1.0.0", optional = true } rayon = "1.5.1" -[target.'cfg(target_os = "macos")'.dependencies] -pasteboard = "0.1.3" - -[target.'cfg(target_os = "windows")'.dependencies] -clipboard-win = "4.0.2" -image = { version = "0.24", default-features = false, features = ["jpeg", "bmp", "jpeg_rayon"] } - [dependencies.image] version = "0.24" default-features = false @@ -56,16 +55,17 @@ optional = true [dependencies.font-kit] version= "0.11" -features= ["loader-freetype-default", "source-fontconfig-default"] +features= ["loader-freetype-default"] -[dependencies.harfbuzz-sys] -version="0.5.0" +[target.'cfg(not(target_os = "windows"))'.dependencies] +harfbuzz-sys = "0.5.0" + +[target.'cfg(target_os = "macos")'.dependencies] +pasteboard = "0.1.3" + +[target.'cfg(target_os = "windows")'.dependencies] +clipboard-win = "4.0.2" +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" } - -[features] -# fearures required for silicon as a application -# disable it when using as a library -default = ["bin"] -bin = ["structopt", "env_logger", "anyhow", "shell-words"] diff --git a/src/bin/silicon/main.rs b/src/bin/silicon/main.rs index e03a7ed..b03408b 100644 --- a/src/bin/silicon/main.rs +++ b/src/bin/silicon/main.rs @@ -51,11 +51,11 @@ pub fn dump_image_to_clipboard(image: &DynamicImage) -> Result<(), Error> { #[cfg(target_os = "windows")] pub fn dump_image_to_clipboard(image: &DynamicImage) -> Result<(), Error> { - let mut temp: Vec = Vec::new(); + let mut temp = std::io::Cursor::new(Vec::new()); // Convert the image to RGB without alpha because the clipboard // of windows doesn't support it. - let image = DynamicImage::ImageRgb8(image.to_rgb()); + let image = DynamicImage::ImageRgb8(image.to_rgb8()); image.write_to(&mut temp, ImageOutputFormat::Bmp)?; @@ -63,7 +63,7 @@ pub fn dump_image_to_clipboard(image: &DynamicImage) -> Result<(), Error> { Clipboard::new_attempts(10).map_err(|e| format_err!("Couldn't open clipboard: {}", e))?; formats::Bitmap - .write_clipboard(&temp) + .write_clipboard(temp.get_ref()) .map_err(|e| format_err!("Failed copy image: {}", e))?; Ok(()) } diff --git a/src/font.rs b/src/font.rs index c0a11e3..89cd9c3 100644 --- a/src/font.rs +++ b/src/font.rs @@ -12,6 +12,7 @@ //! font.draw_text_mut(&mut image, Rgb([255, 0, 0]), 0, 0, FontStyle::REGULAR, "Hello, world"); //! ``` use crate::error::FontError; +#[cfg(not(target_os = "windows"))] use crate::hb_wrapper::{feature_from_tag, HBBuffer, HBFont}; use anyhow::Result; use conv::ValueInto; @@ -193,6 +194,18 @@ impl FontCollection { Ok(Self(fonts)) } + #[cfg(target_os = "windows")] + fn glyph_for_char(&self, c: char, style: FontStyle) -> Option<(u32, &ImageFont, &Font)> { + for font in &self.0 { + let result = font.get_by_style(style); + if let Some(id) = result.glyph_for_char(c) { + return Some((id, font, result)); + } + } + eprintln!("[warning] No font found for character `{}`", c); + None + } + /// get max height of all the fonts pub fn get_font_height(&self) -> u32 { self.0 @@ -202,6 +215,7 @@ impl FontCollection { .unwrap() } + #[cfg(not(target_os = "windows"))] fn shape_text(&self, font: &mut HBFont, text: &str) -> Result> { // feature tags let features = vec![ @@ -221,6 +235,7 @@ impl FontCollection { Ok(glyph_ids) } + #[cfg(not(target_os = "windows"))] fn layout(&self, text: &str, style: FontStyle) -> (Vec, u32) { let mut delta_x = 0; let height = self.get_font_height(); @@ -259,6 +274,42 @@ impl FontCollection { (glyphs, delta_x) } + #[cfg(target_os = "windows")] + fn layout(&self, text: &str, style: FontStyle) -> (Vec, u32) { + let mut delta_x = 0; + let height = self.get_font_height(); + + let glyphs = text + .chars() + .filter_map(|c| { + self.glyph_for_char(c, style).map(|(id, imfont, font)| { + let raster_rect = font + .raster_bounds( + id, + imfont.size, + Transform2F::default(), + HintingOptions::None, + RasterizationOptions::GrayscaleAa, + ) + .unwrap(); + let position = + Vector2I::new(delta_x as i32, height as i32) + raster_rect.origin(); + delta_x += Self::get_glyph_width(font, id, imfont.size); + + PositionedGlyph { + id, + font: font.clone(), + size: imfont.size, + raster_rect, + position, + } + }) + }) + .collect(); + + (glyphs, delta_x) + } + /// Get the width of the given glyph fn get_glyph_width(font: &Font, id: u32, size: f32) -> u32 { let metrics = font.metrics(); diff --git a/src/lib.rs b/src/lib.rs index 94cc683..80cf76f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,8 +21,9 @@ //! //! let mut h = HighlightLines::new(syntax, theme); //! let highlight = LinesWithEndings::from(&code) -//! .map(|line| h.highlight(line, &ps)) -//! .collect::>(); +//! .map(|line| h.highlight_line(line, &ps)) +//! .collect::, _>>() +//! .unwrap(); //! //! let mut formatter = ImageFormatterBuilder::new() //! .font(vec![("Hack", 26.0)]) @@ -42,5 +43,6 @@ pub mod directories; pub mod error; pub mod font; pub mod formatter; +#[cfg(not(target_os = "windows"))] pub mod hb_wrapper; pub mod utils;