diff --git a/Cargo.lock b/Cargo.lock index 676de7c..8b96e66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,18 +2,60 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytemuck" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" + [[package]] name = "calloop" version = "0.9.3" @@ -36,6 +78,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "data-url" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193" +dependencies = [ + "matches", +] + +[[package]] +name = "deflate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" +dependencies = [ + "adler32", +] + [[package]] name = "dlib" version = "0.5.0" @@ -51,6 +139,70 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "flate2" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + +[[package]] +name = "fontconfig-parser" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cea2adebf32a9b104b8ffb308b5fb3b456f04cc76c294c3c85025c8a5d75f4" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122fa73a5566372f9df09768a16e8e3dad7ad18abe07835f1f0b71f84078ba4c" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2 0.5.3", + "ttf-parser", +] + +[[package]] +name = "gif" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "jpeg-decoder" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" + +[[package]] +name = "kurbo" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a53776d271cfb873b17c618af0298445c88afc52837f3e948fa3fafd131f449" +dependencies = [ + "arrayvec 0.7.2", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -82,6 +234,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + [[package]] name = "memchr" version = "2.5.0" @@ -97,6 +255,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -112,6 +279,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +dependencies = [ + "adler", +] + [[package]] name = "nix" version = "0.22.3" @@ -135,18 +311,55 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + [[package]] name = "pkg-config" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +[[package]] +name = "png" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide", +] + [[package]] name = "proc-macro2" version = "1.0.36" @@ -165,12 +378,94 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rctree" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae028b272a6e99d9f8260ceefa3caa09300a8d6c8d2b2001316474bc52122e9" + +[[package]] +name = "resvg" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e702d1e8e00a3a0717b96244cba840f34f542d8f23097c8903266c4e2975658" +dependencies = [ + "gif", + "jpeg-decoder", + "log", + "pico-args", + "png", + "rgb", + "svgfilters", + "svgtypes", + "tiny-skia", + "usvg", +] + +[[package]] +name = "rgb" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74fdc210d8f24a7dbfedc13b04ba5764f5232754ccebfdf5fff1bad791ccbc6" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "roxmltree" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "rustybuzz" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ff94f20221325d000e552781713e53b0d85c1d9551b6f420d12daf5a08eace" +dependencies = [ + "bitflags", + "bytemuck", + "smallvec", + "ttf-parser", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-general-category", + "unicode-script", +] + +[[package]] +name = "safe_arch" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05" +dependencies = [ + "bytemuck", +] + [[package]] name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "smallvec" version = "1.8.0" @@ -188,7 +483,7 @@ dependencies = [ "dlib", "lazy_static", "log", - "memmap2", + "memmap2 0.3.1", "nix", "pkg-config", "wayland-client", @@ -196,12 +491,137 @@ dependencies = [ "wayland-protocols", ] +[[package]] +name = "svg" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e72d8b19ab05827afefcca66bf47040c1e66a0901eb814784c77d4ec118bd309" + +[[package]] +name = "svgfilters" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639abcebc15fdc2df179f37d6f5463d660c1c79cd552c12343a4600827a04bce" +dependencies = [ + "float-cmp", + "rgb", +] + +[[package]] +name = "svgtypes" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dabb3eb59a457c56d5282ab4545609e2cc382b41f6af239bb8d59a7267ef94b3" +dependencies = [ + "siphasher", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "tiny-skia" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bcfd4339bdd4545eabed74b208f2f1555f2e6540fb58135c01f46c0940aa138" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "bytemuck", + "cfg-if", + "png", + "safe_arch", +] + +[[package]] +name = "ttf-parser" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c74c96594835e10fa545e2a51e8709f30b173a092bfd6036ef2cec53376244f3" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" + +[[package]] +name = "unicode-ccc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" + +[[package]] +name = "unicode-general-category" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07547e3ee45e28326cc23faac56d44f58f16ab23e413db526debce3b0bfd2742" + +[[package]] +name = "unicode-script" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dd944fd05f2f0b5c674917aea8a4df6af84f2d8de3fe8d988b95d28fb8fb09" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "usvg" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a261d60a7215fa339482047cc3dafd4e22e2bf34396aaebef2b707355bbb39c0" +dependencies = [ + "base64", + "data-url", + "flate2", + "float-cmp", + "fontdb", + "kurbo", + "log", + "pico-args", + "rctree", + "roxmltree", + "rustybuzz", + "simplecss", + "siphasher", + "svgtypes", + "ttf-parser", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wayland-client" version = "0.29.4" @@ -275,6 +695,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "weezl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" + [[package]] name = "winapi" version = "0.3.9" @@ -301,7 +727,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" name = "wl-seasonal-hours-clock" version = "0.1.0" dependencies = [ + "chrono", + "resvg", "smithay-client-toolkit", + "svg", + "tiny-skia", + "usvg", ] [[package]] @@ -318,3 +749,15 @@ name = "xml-rs" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "xmlparser" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8" + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" diff --git a/Cargo.toml b/Cargo.toml index 808823b..150698c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,8 @@ edition = "2021" [dependencies] smithay-client-toolkit = "0.15" +chrono = "0.4" +svg = "0.10" +usvg = "0.22" +tiny-skia = "0.6" +resvg = "0.22" diff --git a/src/main.rs b/src/main.rs index 923868e..c23055e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,93 @@ extern crate smithay_client_toolkit as sctk; +use std::time::SystemTime; + +use chrono::Timelike; +use chrono::prelude::Local; use sctk::reexports::client::protocol::{wl_shm, wl_surface}; use sctk::shm::AutoMemPool; use sctk::window::{Event as WEvent, FallbackFrame}; +use svg::Document; +use svg::node::Text as TextNode; +use svg::node::element::{Group, Line, Rectangle, Style, Text}; sctk::default_environment!(SeasonalClock, desktop); +fn seconds_to_degrees(seconds: i32) -> f32 { + seconds as f32 * 360.0 / 86400.0 +} + +fn time_to_degrees( + timestamp: i32 // should be time/timestamp +) -> f32 { + seconds_to_degrees(timestamp) +} + +fn gen_svg() -> Document { + // These should be calculated + let local_timestamp = Local::now(); + let local_time = local_timestamp.time().num_seconds_from_midnight() as i32; + + // TODO: These should be calculated instead of hardcoded + let image_width = 700u32; + let local_hour_font_size = 16.5; + let hour_name_font_size = 13.37699; + let outer_r = (image_width as f32) / 2.0 - 3.0 * hour_name_font_size; + let ring_width = hour_name_font_size * 3.0; + let border = Rectangle::new() + .set("x", 0i32) + .set("y", 0i32) + .set("width", 700i32) + .set("height", 700i32) + .set("id", "border"); + let stylesheet = Style::new("\ + #border {stroke: none; fill: rgb(19, 17, 30); } + .local-hour {stroke: none; fill: rgb(238, 187, 85);} + .dial {stroke-width: 2px; stroke: rgb(238, 187, 85);}"); + let mut local_clock = Group::new() + .set("id", "local-clock"); + + for hour in 0i32..24 { + let hour_str = match hour { + 0 => "Midnight".to_string(), + 12 => "Noon".to_string(), + _ => hour.to_string(), + }; + let rotation = hour * 15; + let hour_name = TextNode::new(hour_str); + let hour_node = Text::new() + .set("class", "local-hour") + .set("transform", format!("rotate({}, 350, 350)", 180 + rotation)) + .set("x", (image_width as f32) / 2.0) + .set("y", (image_width as f32) / 2.0 - outer_r - local_hour_font_size / 2.0) + .set("text-anchor", "middle") + .set("font-size", local_hour_font_size as f32) + .add(hour_name); + local_clock = local_clock.add(hour_node); + } + + let dial = Line::new() + .set("id", "dial") + .set("class", "dial") + .set("transform", format!("rotate({}, {}, {})", time_to_degrees(local_time), image_width / 2, image_width / 2)) + .set("x1", image_width / 2) + .set("y1", image_width as f32 / 2.0 + outer_r * 0.5) + .set("x2", image_width / 2) + .set("y2", image_width as f32 / 2.0 + outer_r - ring_width + hour_name_font_size); + + Document::new() + .set("viewBox", (0i32, 0i32, 700i32, 700i32)) + .set("width", 700i32) + .set("height", 700i32) + .set("xmlns:xlink", "http://www.w3.org/1999/xlink") + .add(stylesheet) + .add(border) + .add(local_clock) + .add(dial) +} + fn main() { - let (env, _display, mut queue) = sctk::new_default_environment!(SeasonalClock, desktop) + let (env, display, mut queue) = sctk::new_default_environment!(SeasonalClock, desktop) .expect("Unable to connect to a Wayland compositor"); let surface = env @@ -44,7 +124,7 @@ fn main() { let mut pool = env.create_auto_pool().expect("Failed to create the memory pool."); let mut need_redraw = false; - let mut dimensions = (100, 100); + let mut dimensions = (700, 700); if !env.get_shell().unwrap().needs_configure() { redraw(&mut pool, window.surface(), dimensions) @@ -52,7 +132,25 @@ fn main() { window.refresh() } + let now = SystemTime::now(); + let mut last_elapsed = 0; + loop { + // Update every second + // TODO: There’s probably a better way to do this… + match now.elapsed() { + Ok(elapsed) => { + let new_elapsed = elapsed.as_secs(); + + if new_elapsed != last_elapsed { + need_redraw = true; + last_elapsed = new_elapsed; + } + } + Err(e) => { + println!("Error: {:?}", e); + } + } match next_action.take() { Some(WEvent::Close) => break, Some(WEvent::Refresh) => { @@ -75,15 +173,26 @@ fn main() { if need_redraw { need_redraw = false; - redraw( - &mut pool, - window.surface(), - dimensions, - ) + redraw(&mut pool, window.surface(), dimensions) .expect("Failed to draw") } - queue.dispatch(&mut next_action, |_, _, _| {}).unwrap(); + if let Err(e) = display.flush() { + if e.kind() != ::std::io::ErrorKind::WouldBlock { + eprintln!("Error while trying to flush the wayland socket: {:?}", e); + } + } + + if let Some(guard) = queue.prepare_read() { + if let Err(e) = guard.read_events() { + if e.kind() != ::std::io::ErrorKind::WouldBlock { + eprintln!("Error while trying to read from the wayland socked: {:?}", e); + } + } + } + + queue.dispatch_pending(&mut next_action, |_, _, _| {}) + .expect("Failed to dispatch all messages."); } } @@ -92,6 +201,14 @@ fn redraw( surface: &wl_surface::WlSurface, (buf_x, buf_y): (u32, u32), ) -> Result<(), ::std::io::Error> { + let document = gen_svg(); + + let bytes = document.to_string(); + let mut opt = usvg::Options::default(); + opt.fontdb.load_system_fonts(); + opt.font_family = "Liberation Serif".to_string(); + let svg_tree = usvg::Tree::from_str(&bytes, &opt.to_ref()).unwrap(); + let (canvas, new_buffer) = pool.buffer( buf_x as i32, buf_y as i32, @@ -99,12 +216,28 @@ fn redraw( wl_shm::Format::Argb8888, )?; + let image_size = ::std::cmp::min(buf_x, buf_y); + let move_x = (buf_x - image_size) as f32 / 2.0; + let move_y = (buf_y - image_size) as f32 / 2.0; + let mut pixmap = tiny_skia::Pixmap::new(buf_x, buf_y).unwrap(); + resvg::render(&svg_tree, usvg::FitTo::Size(image_size, image_size), tiny_skia::Transform::from_translate(move_x, move_y), pixmap.as_mut()).unwrap(); // We do not have anything to draw yet, so draw an empty surface - for dst_pixel in canvas.chunks_exact_mut(4) { - dst_pixel[0] = 0x00; - dst_pixel[1] = 0x00; - dst_pixel[2] = 0x00; - dst_pixel[3] = 0xFF; + for (dst_pixel, src_pixel) in canvas.chunks_exact_mut(4).zip(pixmap.pixels()) { + let r = src_pixel.red() as u32; + let g = src_pixel.green() as u32; + let b = src_pixel.blue() as u32; + let a = src_pixel.alpha() as u32; + + let r = ::std::cmp::min(0xFF, (0xFF * (0xFF - a) + a * r) / 0xFF); + let g = ::std::cmp::min(0xFF, (0xFF * (0xFF - a) + a * g) / 0xFF); + let b = ::std::cmp::min(0xFF, (0xFF * (0xFF - a) + a * b) / 0xFF); + + let pixel: [u8; 4] = ((0xFF << 24) + (r << 16) + (g << 8) + b).to_ne_bytes(); + + dst_pixel[0] = pixel[0]; + dst_pixel[1] = pixel[1]; + dst_pixel[2] = pixel[2]; + dst_pixel[3] = pixel[3]; } surface.attach(Some(&new_buffer), 0, 0);