From 603ec82a5ee6dc28b2974bd08fd3b48dc1c69cf1 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 7 Feb 2022 10:38:08 +0100 Subject: [PATCH 1/3] cargo deny: clarify MPL-2.0 license and use un-patched ureq again (#1222) See https://github.com/algesten/ureq/issues/478#issuecomment-1031029647 --- Cargo.lock | 81 ++++++++---------------------------------------------- Cargo.toml | 3 -- deny.toml | 1 + 3 files changed, 13 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92e60de2..286adabc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2239,12 +2239,6 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - [[package]] name = "ordered-multimap" version = "0.3.1" @@ -2693,27 +2687,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" -dependencies = [ - "base64", -] - [[package]] name = "ryu" version = "1.0.9" @@ -2735,16 +2708,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -dependencies = [ - "lazy_static", - "winapi", -] - [[package]] name = "scoped-tls" version = "1.0.0" @@ -2767,29 +2730,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fed7948b6c68acbb6e20c334f55ad635dc0f75506963de4464289fbd3b051ac" -dependencies = [ - "bitflags", - "core-foundation 0.9.2", - "core-foundation-sys 0.8.3", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57321bf8bc2362081b2599912d2961fe899c0efadf1b4b2f8d48b3e253bb96c" -dependencies = [ - "core-foundation-sys 0.8.3", - "libc", -] - [[package]] name = "semver" version = "1.0.4" @@ -3002,12 +2942,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "sync_wrapper" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" - [[package]] name = "syntect" version = "4.6.0" @@ -3289,7 +3223,8 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" version = "2.4.0" -source = "git+https://github.com/emilk/ureq/?branch=opt-in-webpki-roots#d4ca2ca620b65854c3428306b03ab7ef562bf796" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9399fa2f927a3d327187cbd201480cee55bee6ac5d3c77dd27f0c6814cff16d5" dependencies = [ "base64", "chunked_transfer", @@ -3297,10 +3232,9 @@ dependencies = [ "log", "once_cell", "rustls", - "rustls-native-certs", - "sync_wrapper", "url", "webpki", + "webpki-roots", ] [[package]] @@ -3542,6 +3476,15 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki", +] + [[package]] name = "wepoll-ffi" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index f3457800..53b381e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,3 @@ opt-level = 2 # fast and small wasm, basically same as `opt-level = 's'` # opt-level = 3 # unecessarily large wasm for no performance gain # debug = true # include debug symbols, useful when profiling wasm - -[patch.crates-io] -ureq = { git = "https://github.com/emilk/ureq/", branch = "opt-in-webpki-roots" } # See https://github.com/algesten/ureq/pull/479 / https://github.com/algesten/ureq/issues/478 diff --git a/deny.toml b/deny.toml index afd1bb45..c58fa9ba 100644 --- a/deny.toml +++ b/deny.toml @@ -49,6 +49,7 @@ allow = [ "CC0-1.0", # https://creativecommons.org/publicdomain/zero/1.0/ "ISC", # https://tldrlegal.com/license/-isc-license "MIT", # https://tldrlegal.com/license/mit-license + "MPL-2.0", # https://www.mozilla.org/en-US/MPL/2.0/FAQ/ - see Q11 "OpenSSL", # https://www.openssl.org/source/license.html "Zlib", # https://tldrlegal.com/license/zlib-libpng-license-(zlib) ] From 2802e03526e9b4918457b08f3784d154177d5c6d Mon Sep 17 00:00:00 2001 From: Erlend Walstad <96946613+lampsitter@users.noreply.github.com> Date: Mon, 7 Feb 2022 11:29:16 +0100 Subject: [PATCH 2/3] Per-side margins with new struct Margin (#1219) --- CHANGELOG.md | 1 + egui/src/containers/frame.rs | 71 ++++++++++++++++++++++++++++----- egui/src/containers/mod.rs | 2 +- egui/src/containers/popup.rs | 2 +- egui/src/containers/resize.rs | 2 +- egui/src/containers/window.rs | 2 +- egui/src/style.rs | 42 ++++++++++++++++--- egui/src/widgets/plot/legend.rs | 2 +- 8 files changed, 102 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e84aad..e2a583b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w * `TextStyle` is no longer `Copy` ([#1154](https://github.com/emilk/egui/pull/1154)). * Replaced `TextEdit::text_style` with `TextEdit::font` ([#1154](https://github.com/emilk/egui/pull/1154)). * Replaced `corner_radius: f32` with `rounding: Rounding`, allowing per-corner rounding settings ([#1206](https://github.com/emilk/egui/pull/1206)). +* Replaced Frame's `margin: Vec2` with `margin: Margin`, allowing for different margins on opposing sides ([#1219](https://github.com/emilk/egui/pull/1219)). * `Plot::highlight` now takes a `bool` argument ([#1159](https://github.com/emilk/egui/pull/1159)). * `ScrollArea::show` now returns a `ScrollAreaOutput`, so you might need to add `.inner` after the call to it ([#1166](https://github.com/emilk/egui/pull/1166)). diff --git a/egui/src/containers/frame.rs b/egui/src/containers/frame.rs index c5c5a61a..044b96a9 100644 --- a/egui/src/containers/frame.rs +++ b/egui/src/containers/frame.rs @@ -3,12 +3,55 @@ use crate::{layers::ShapeIdx, *}; use epaint::*; +#[derive(Clone, Copy, Debug, Default, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct Margin { + pub left: f32, + pub right: f32, + pub top: f32, + pub bottom: f32, +} + +impl Margin { + #[inline] + pub fn same(margin: f32) -> Self { + Self { + left: margin, + right: margin, + top: margin, + bottom: margin, + } + } + + /// Margins with the same size on opposing sides + #[inline] + pub fn symmetric(x: f32, y: f32) -> Self { + Self { + left: x, + right: x, + top: y, + bottom: y, + } + } + + /// Total margins on both sides + pub fn sum(&self) -> Vec2 { + Vec2::new(self.left + self.right, self.top + self.bottom) + } +} + +impl From for Margin { + fn from(v: Vec2) -> Self { + Self::symmetric(v.x, v.y) + } +} + /// Color and margin of a rectangular background of a [`Ui`]. #[derive(Clone, Copy, Debug, Default, PartialEq)] #[must_use = "You should call .show()"] pub struct Frame { /// On each side - pub margin: Vec2, + pub margin: Margin, pub rounding: Rounding, pub shadow: Shadow, pub fill: Color32, @@ -23,7 +66,7 @@ impl Frame { /// For when you want to group a few widgets together within a frame. pub fn group(style: &Style) -> Self { Self { - margin: Vec2::splat(6.0), // symmetric looks best in corners when nesting + margin: Margin::same(6.0), // symmetric looks best in corners when nesting rounding: style.visuals.widgets.noninteractive.rounding, stroke: style.visuals.widgets.noninteractive.bg_stroke, ..Default::default() @@ -32,7 +75,7 @@ impl Frame { pub(crate) fn side_top_panel(style: &Style) -> Self { Self { - margin: Vec2::new(8.0, 2.0), + margin: Margin::symmetric(8.0, 2.0), rounding: Rounding::none(), fill: style.visuals.window_fill(), stroke: style.visuals.window_stroke(), @@ -42,7 +85,7 @@ impl Frame { pub(crate) fn central_panel(style: &Style) -> Self { Self { - margin: Vec2::new(8.0, 8.0), + margin: Margin::symmetric(8.0, 8.0), rounding: Rounding::none(), fill: style.visuals.window_fill(), stroke: Default::default(), @@ -52,7 +95,7 @@ impl Frame { pub fn window(style: &Style) -> Self { Self { - margin: style.spacing.window_padding, + margin: style.spacing.window_margin, rounding: style.visuals.window_rounding, shadow: style.visuals.window_shadow, fill: style.visuals.window_fill(), @@ -62,7 +105,7 @@ impl Frame { pub fn menu(style: &Style) -> Self { Self { - margin: Vec2::splat(1.0), + margin: Margin::same(1.0), rounding: style.visuals.widgets.noninteractive.rounding, shadow: style.visuals.popup_shadow, fill: style.visuals.window_fill(), @@ -72,7 +115,7 @@ impl Frame { pub fn popup(style: &Style) -> Self { Self { - margin: style.spacing.window_padding, + margin: style.spacing.window_margin, rounding: style.visuals.widgets.noninteractive.rounding, shadow: style.visuals.popup_shadow, fill: style.visuals.window_fill(), @@ -83,7 +126,7 @@ impl Frame { /// dark canvas to draw on pub fn dark_canvas(style: &Style) -> Self { Self { - margin: Vec2::new(10.0, 10.0), + margin: Margin::symmetric(10.0, 10.0), rounding: style.visuals.widgets.noninteractive.rounding, fill: Color32::from_black_alpha(250), stroke: style.visuals.window_stroke(), @@ -109,7 +152,7 @@ impl Frame { } /// Margin on each side of the frame. - pub fn margin(mut self, margin: impl Into) -> Self { + pub fn margin(mut self, margin: impl Into) -> Self { self.margin = margin.into(); self } @@ -137,7 +180,10 @@ impl Frame { pub fn begin(self, ui: &mut Ui) -> Prepared { let where_to_put_background = ui.painter().add(Shape::Noop); let outer_rect_bounds = ui.available_rect_before_wrap(); - let mut inner_rect = outer_rect_bounds.shrink2(self.margin); + + let mut inner_rect = outer_rect_bounds; + inner_rect.min += Vec2::new(self.margin.left, self.margin.top); + inner_rect.max -= Vec2::new(self.margin.right, self.margin.bottom); // Make sure we don't shrink to the negative: inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x); @@ -197,7 +243,10 @@ impl Frame { impl Prepared { pub fn outer_rect(&self) -> Rect { - self.content_ui.min_rect().expand2(self.frame.margin) + let mut rect = self.content_ui.min_rect(); + rect.min -= Vec2::new(self.frame.margin.left, self.frame.margin.top); + rect.max += Vec2::new(self.frame.margin.right, self.frame.margin.bottom); + rect } pub fn end(self, ui: &mut Ui) -> Response { diff --git a/egui/src/containers/mod.rs b/egui/src/containers/mod.rs index f151b8e9..cc457a51 100644 --- a/egui/src/containers/mod.rs +++ b/egui/src/containers/mod.rs @@ -16,7 +16,7 @@ pub use { area::Area, collapsing_header::{CollapsingHeader, CollapsingResponse}, combo_box::*, - frame::Frame, + frame::{Frame, Margin}, panel::{CentralPanel, SidePanel, TopBottomPanel}, popup::*, resize::Resize, diff --git a/egui/src/containers/popup.rs b/egui/src/containers/popup.rs index ffe36672..c8cbdb67 100644 --- a/egui/src/containers/popup.rs +++ b/egui/src/containers/popup.rs @@ -302,7 +302,7 @@ pub fn popup_below_widget( frame .show(ui, |ui| { ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| { - ui.set_width(widget_response.rect.width() - 2.0 * frame_margin.x); + ui.set_width(widget_response.rect.width() - frame_margin.sum().x); add_contents(ui) }) .inner diff --git a/egui/src/containers/resize.rs b/egui/src/containers/resize.rs index 5dd46dbe..2f31ff05 100644 --- a/egui/src/containers/resize.rs +++ b/egui/src/containers/resize.rs @@ -178,7 +178,7 @@ impl Resize { .at_least(self.min_size) .at_most(self.max_size) .at_most( - ui.input().screen_rect().size() - 2.0 * ui.spacing().window_padding, // hack for windows + ui.input().screen_rect().size() - ui.spacing().window_margin.sum(), // hack for windows ); State { diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index 9c439b26..4e1eb70d 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -301,7 +301,7 @@ impl<'open> Window<'open> { } else { 0.0 }; - let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height); + let margins = frame.margin.sum() + vec2(0.0, title_bar_height); interact( window_interaction, diff --git a/egui/src/style.rs b/egui/src/style.rs index a1430850..d13548a6 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -2,7 +2,7 @@ #![allow(clippy::if_same_then_else)] -use crate::{color::*, emath::*, FontFamily, FontId, Response, RichText, WidgetText}; +use crate::{color::*, emath::*, FontFamily, FontId, Margin, Response, RichText, WidgetText}; use epaint::{mutex::Arc, Rounding, Shadow, Stroke}; use std::collections::BTreeMap; @@ -220,8 +220,8 @@ pub struct Spacing { /// widgets `A` and `B` you need to change `item_spacing` before adding `A`. pub item_spacing: Vec2, - /// Horizontal and vertical padding within a window frame. - pub window_padding: Vec2, + /// Horizontal and vertical margins within a window frame. + pub window_margin: Margin, /// Button size is text size plus this on each side pub button_padding: Vec2, @@ -528,7 +528,7 @@ impl Default for Spacing { fn default() -> Self { Self { item_spacing: vec2(8.0, 3.0), - window_padding: Vec2::splat(6.0), + window_margin: Margin::same(6.0), button_padding: vec2(4.0, 1.0), indent: 18.0, // match checkbox/radio-button with `button_padding.x + icon_width + icon_spacing` interact_size: vec2(40.0, 18.0), @@ -803,7 +803,7 @@ impl Spacing { pub fn ui(&mut self, ui: &mut crate::Ui) { let Self { item_spacing, - window_padding, + window_margin, button_padding, indent, interact_size, @@ -818,7 +818,37 @@ impl Spacing { } = self; ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing")); - ui.add(slider_vec2(window_padding, 0.0..=20.0, "Window padding")); + + let margin_range = 0.0..=20.0; + ui.horizontal(|ui| { + ui.add( + DragValue::new(&mut window_margin.left) + .clamp_range(margin_range.clone()) + .prefix("left: "), + ); + ui.add( + DragValue::new(&mut window_margin.right) + .clamp_range(margin_range.clone()) + .prefix("right: "), + ); + + ui.label("Window margins x"); + }); + + ui.horizontal(|ui| { + ui.add( + DragValue::new(&mut window_margin.top) + .clamp_range(margin_range.clone()) + .prefix("top: "), + ); + ui.add( + DragValue::new(&mut window_margin.bottom) + .clamp_range(margin_range) + .prefix("bottom: "), + ); + ui.label("Window margins y"); + }); + ui.add(slider_vec2(button_padding, 0.0..=20.0, "Button padding")); ui.add(slider_vec2(interact_size, 4.0..=60.0, "Interact size")) .on_hover_text("Minimum size of an interactive widget"); diff --git a/egui/src/widgets/plot/legend.rs b/egui/src/widgets/plot/legend.rs index 71f3dfdc..6c60c6a3 100644 --- a/egui/src/widgets/plot/legend.rs +++ b/egui/src/widgets/plot/legend.rs @@ -239,7 +239,7 @@ impl Widget for &mut LegendWidget { legend_ui .scope(|ui| { let background_frame = Frame { - margin: vec2(8.0, 4.0), + margin: vec2(8.0, 4.0).into(), rounding: ui.style().visuals.window_rounding, shadow: epaint::Shadow::default(), fill: ui.style().visuals.extreme_bg_color, From defc400c21aaf3fc61f4a7530f13fdbe5991fcc1 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 9 Feb 2022 08:12:12 +0100 Subject: [PATCH 3/3] Add an example of how to display an SVG image in egui (#1228) --- Cargo.lock | 267 ++++++++++++++++++++++- eframe/Cargo.toml | 5 + eframe/examples/rustacean-flat-happy.svg | 33 +++ eframe/examples/svg.rs | 108 +++++++++ eframe/src/lib.rs | 2 +- egui/src/introspection.rs | 2 - egui/src/lib.rs | 2 +- egui_glow/Cargo.toml | 3 - 8 files changed, 411 insertions(+), 11 deletions(-) create mode 100644 eframe/examples/rustacean-flat-happy.svg create mode 100644 eframe/examples/svg.rs diff --git a/Cargo.lock b/Cargo.lock index 286adabc..6c5cbabf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,18 @@ dependencies = [ "winapi", ] +[[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 = "ashpd" version = "0.2.2" @@ -831,6 +843,15 @@ dependencies = [ "syn", ] +[[package]] +name = "data-url" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193" +dependencies = [ + "matches", +] + [[package]] name = "dconf_rs" version = "0.3.0" @@ -980,7 +1001,10 @@ dependencies = [ "epi", "image", "poll-promise", + "resvg", "rfd", + "tiny-skia", + "usvg", ] [[package]] @@ -1060,7 +1084,6 @@ dependencies = [ "epi", "glow", "glutin", - "image", "memoffset", "tracing", "wasm-bindgen", @@ -1298,12 +1321,29 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fontdb" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b07f5c05414a0d8caba4c17eef8dc8b5c8955fc7c68d324191c7a56d3f3449" +dependencies = [ + "log", + "memmap2 0.5.2", + "ttf-parser 0.12.3", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -1723,7 +1763,7 @@ dependencies = [ "bytemuck", "byteorder", "color_quant", - "jpeg-decoder", + "jpeg-decoder 0.2.1", "num-iter", "num-rational", "num-traits", @@ -1793,6 +1833,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jpeg-decoder" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" + [[package]] name = "jpeg-decoder" version = "0.2.1" @@ -1814,6 +1860,15 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +[[package]] +name = "kurbo" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb348d766edbac91ba1eb83020d96f4f8867924d194393083c15a51f185e6a82" +dependencies = [ + "arrayvec", +] + [[package]] name = "lazy-bytes-cast" version = "5.0.1" @@ -1911,6 +1966,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe3179b85e1fd8b14447cbebadb75e45a1002f541b925f0bfec366d56a81c56d" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -2274,7 +2338,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef05f2882a8b3e7acc10c153ade2631f7bfc8ce00d2bf3fb8f4e9d2ae6ea5c3" dependencies = [ - "ttf-parser", + "ttf-parser 0.14.0", ] [[package]] @@ -2332,6 +2396,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + [[package]] name = "pin-project-lite" version = "0.2.8" @@ -2550,6 +2620,12 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rctree" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae028b272a6e99d9f8260ceefa3caa09300a8d6c8d2b2001316474bc52122e9" + [[package]] name = "redox_syscall" version = "0.2.10" @@ -2592,6 +2668,23 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "resvg" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d94a32ca845cdda27237a40beba9bd3d3858ac8fc5356eb9442bdeecfe34d9e0" +dependencies = [ + "jpeg-decoder 0.1.22", + "log", + "pico-args", + "png", + "rgb", + "svgfilters", + "svgtypes", + "tiny-skia", + "usvg", +] + [[package]] name = "rfd" version = "0.7.0" @@ -2618,6 +2711,15 @@ dependencies = [ "windows", ] +[[package]] +name = "rgb" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a374af9a0e5fdcdd98c1c7b64f05004f9ea2555b6c75f211daa81268a3c50f1" +dependencies = [ + "bytemuck", +] + [[package]] name = "ring" version = "0.16.20" @@ -2644,6 +2746,15 @@ dependencies = [ "serde", ] +[[package]] +name = "roxmltree" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b" +dependencies = [ + "xmlparser", +] + [[package]] name = "rust-ini" version = "0.17.0" @@ -2687,12 +2798,37 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustybuzz" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44561062e583c4873162861261f16fd1d85fe927c4904d71329a4fe43dc355ef" +dependencies = [ + "bitflags", + "bytemuck", + "smallvec", + "ttf-parser 0.12.3", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-general-category", + "unicode-script", +] + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "safe_arch" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05" +dependencies = [ + "bytemuck", +] + [[package]] name = "safemem" version = "0.3.3" @@ -2828,6 +2964,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" + [[package]] name = "slab" version = "0.4.5" @@ -2860,7 +3011,7 @@ dependencies = [ "dlib", "lazy_static", "log", - "memmap2", + "memmap2 0.3.1", "nix 0.22.3", "pkg-config", "wayland-client", @@ -2931,6 +3082,25 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[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 = "syn" version = "1.0.86" @@ -3051,6 +3221,20 @@ dependencies = [ "num_threads", ] +[[package]] +name = "tiny-skia" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bcfd4339bdd4545eabed74b208f2f1555f2e6540fb58135c01f46c0940aa138" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if 1.0.0", + "png", + "safe_arch", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -3154,6 +3338,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ttf-parser" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" + [[package]] name = "ttf-parser" version = "0.14.0" @@ -3187,6 +3377,24 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +[[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-normalization" version = "0.1.19" @@ -3196,6 +3404,18 @@ dependencies = [ "tinyvec", ] +[[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-width" version = "0.1.9" @@ -3249,6 +3469,33 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "usvg" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f064d38f79ff69e3160e2fba884e4ede897061c15178041a3976371c68cab1" +dependencies = [ + "base64", + "data-url", + "flate2", + "float-cmp", + "fontdb", + "kurbo", + "log", + "pico-args", + "rctree", + "roxmltree", + "rustybuzz", + "simplecss", + "siphasher", + "svgtypes", + "ttf-parser 0.12.3", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + [[package]] name = "valuable" version = "0.1.0" @@ -3673,6 +3920,18 @@ 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" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/eframe/Cargo.toml b/eframe/Cargo.toml index 35265b99..a9ff85c3 100644 --- a/eframe/Cargo.toml +++ b/eframe/Cargo.toml @@ -62,9 +62,14 @@ egui_glow = { version = "0.16.0", path = "../egui_glow", default-features = fals [target.'cfg(target_arch = "wasm32")'.dependencies] egui_web = { version = "0.16.0", path = "../egui_web", default-features = false, features = ["glow"] } + [dev-dependencies] ehttp = "0.2" image = { version = "0.24", default-features = false, features = ["jpeg", "png"] } poll-promise = "0.1" rfd = "0.7" +# svg.rs example: +resvg = "0.20" +tiny-skia = "0.6" +usvg = "0.20" diff --git a/eframe/examples/rustacean-flat-happy.svg b/eframe/examples/rustacean-flat-happy.svg new file mode 100644 index 00000000..c7f240dd --- /dev/null +++ b/eframe/examples/rustacean-flat-happy.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eframe/examples/svg.rs b/eframe/examples/svg.rs new file mode 100644 index 00000000..e4aff0cf --- /dev/null +++ b/eframe/examples/svg.rs @@ -0,0 +1,108 @@ +//! A good way of displaying an SVG image in egui. +//! +//! Requires the dependencies `resvg`, `tiny-skia`, `usvg` +use eframe::{egui, epi}; + +/// Load an SVG and rasterize it into an egui image. +fn load_svg_data(svg_data: &[u8]) -> Result { + let mut opt = usvg::Options::default(); + opt.fontdb.load_system_fonts(); + + let rtree = usvg::Tree::from_data(svg_data, &opt.to_ref()).map_err(|err| err.to_string())?; + + let pixmap_size = rtree.svg_node().size.to_screen_size(); + let [w, h] = [pixmap_size.width(), pixmap_size.height()]; + + let mut pixmap = tiny_skia::Pixmap::new(w, h) + .ok_or_else(|| format!("Failed to create SVG Pixmap of size {}x{}", w, h))?; + + resvg::render( + &rtree, + usvg::FitTo::Original, + tiny_skia::Transform::default(), + pixmap.as_mut(), + ) + .ok_or_else(|| "Failed to render SVG".to_owned())?; + + let image = egui::ColorImage::from_rgba_unmultiplied( + [pixmap.width() as _, pixmap.height() as _], + pixmap.data(), + ); + + Ok(image) +} + +// ---------------------------------------------------------------------------- + +/// An SVG image to be shown in egui +struct SvgImage { + image: egui::ColorImage, + texture: Option, +} + +impl SvgImage { + /// Pass itn the bytes of an SVG that you've loaded from disk + pub fn from_svg_data(bytes: &[u8]) -> Result { + Ok(Self { + image: load_svg_data(bytes)?, + texture: None, + }) + } + + pub fn show_max_size(&mut self, ui: &mut egui::Ui, max_size: egui::Vec2) -> egui::Response { + let mut desired_size = egui::vec2(self.image.width() as _, self.image.height() as _); + desired_size *= (max_size.x / desired_size.x).min(1.0); + desired_size *= (max_size.y / desired_size.y).min(1.0); + self.show_size(ui, desired_size) + } + + pub fn show_size(&mut self, ui: &mut egui::Ui, desired_size: egui::Vec2) -> egui::Response { + // We need to convert the SVG to a texture to display it: + // Future improvement: tell backend to do mip-mapping of the image to + // make it look smoother when downsized. + let svg_texture = self + .texture + .get_or_insert_with(|| ui.ctx().load_texture("svg", self.image.clone())); + ui.image(svg_texture, desired_size) + } +} + +// ---------------------------------------------------------------------------- + +struct MyApp { + svg_image: SvgImage, +} + +impl Default for MyApp { + fn default() -> Self { + Self { + svg_image: SvgImage::from_svg_data(include_bytes!("rustacean-flat-happy.svg")).unwrap(), + } + } +} + +impl epi::App for MyApp { + fn name(&self) -> &str { + "svg example" + } + + fn update(&mut self, ctx: &egui::Context, _frame: &epi::Frame) { + egui::CentralPanel::default().show(ctx, |ui| { + ui.heading("SVG example"); + ui.label("The SVG is rasterized and displayed as a texture."); + + ui.separator(); + + let max_size = ui.available_size(); + self.svg_image.show_max_size(ui, max_size); + }); + } +} + +fn main() { + let options = eframe::NativeOptions { + initial_window_size: Some(egui::vec2(1000.0, 700.0)), + ..Default::default() + }; + eframe::run_native(Box::new(MyApp::default()), options); +} diff --git a/eframe/src/lib.rs b/eframe/src/lib.rs index d0ba574d..31e9643e 100644 --- a/eframe/src/lib.rs +++ b/eframe/src/lib.rs @@ -65,7 +65,7 @@ )] #![allow(clippy::needless_doctest_main)] -pub use {egui, epi}; +pub use {egui, egui::emath, egui::epaint, epi}; #[cfg(not(target_arch = "wasm32"))] pub use epi::NativeOptions; diff --git a/egui/src/introspection.rs b/egui/src/introspection.rs index d0b34638..3726b808 100644 --- a/egui/src/introspection.rs +++ b/egui/src/introspection.rs @@ -24,8 +24,6 @@ pub fn font_id_ui(ui: &mut Ui, font_id: &mut FontId) { // Show font texture in demo Ui pub(crate) fn font_texture_ui(ui: &mut Ui, [width, height]: [usize; 2]) -> Response { - use epaint::Mesh; - ui.vertical(|ui| { let color = if ui.visuals().dark_mode { Color32::WHITE diff --git a/egui/src/lib.rs b/egui/src/lib.rs index 646780f3..fdf37174 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -387,7 +387,7 @@ pub use epaint::{ color, mutex, text::{FontData, FontDefinitions, FontFamily, FontId}, textures::TexturesDelta, - AlphaImage, ClippedMesh, Color32, ColorImage, ImageData, Rgba, Rounding, Shape, Stroke, + AlphaImage, ClippedMesh, Color32, ColorImage, ImageData, Mesh, Rgba, Rounding, Shape, Stroke, TextureHandle, TextureId, }; diff --git a/egui_glow/Cargo.toml b/egui_glow/Cargo.toml index fe6870ee..30c680e4 100644 --- a/egui_glow/Cargo.toml +++ b/egui_glow/Cargo.toml @@ -73,6 +73,3 @@ glutin = { version = "0.28.0", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] web-sys = { version = "0.3", features=["console"] } wasm-bindgen = { version = "0.2" } - -[dev-dependencies] -image = { version = "0.24", default-features = false, features = ["png"] }