Reduce binary size with more inlining and less monomorphization

5%=150kB savings on egui_demo_app wasm
This commit is contained in:
Emil Ernerfeldt 2021-04-24 09:54:11 +02:00
parent f38f68318d
commit 0f112db550
4 changed files with 97 additions and 18 deletions

View file

@ -98,6 +98,7 @@ pub enum Direction {
}
impl Direction {
#[inline(always)]
pub fn is_horizontal(self) -> bool {
match self {
Direction::LeftToRight | Direction::RightToLeft => true,
@ -105,6 +106,7 @@ impl Direction {
}
}
#[inline(always)]
pub fn is_vertical(self) -> bool {
match self {
Direction::LeftToRight | Direction::RightToLeft => false,
@ -161,6 +163,7 @@ impl Default for Layout {
/// ## Constructors
impl Layout {
#[inline(always)]
pub fn left_to_right() -> Self {
Self {
main_dir: Direction::LeftToRight,
@ -172,6 +175,7 @@ impl Layout {
}
}
#[inline(always)]
pub fn right_to_left() -> Self {
Self {
main_dir: Direction::RightToLeft,
@ -183,6 +187,7 @@ impl Layout {
}
}
#[inline(always)]
pub fn top_down(cross_align: Align) -> Self {
Self {
main_dir: Direction::TopDown,
@ -195,10 +200,12 @@ impl Layout {
}
/// Top-down layout justifed so that buttons etc fill the full available width.
#[inline(always)]
pub fn top_down_justified(cross_align: Align) -> Self {
Self::top_down(cross_align).with_cross_justify(true)
}
#[inline(always)]
pub fn bottom_up(cross_align: Align) -> Self {
Self {
main_dir: Direction::BottomUp,
@ -210,6 +217,7 @@ impl Layout {
}
}
#[inline(always)]
pub fn from_main_dir_and_cross_align(main_dir: Direction, cross_align: Align) -> Self {
Self {
main_dir,
@ -221,6 +229,7 @@ impl Layout {
}
}
#[inline(always)]
pub fn centered_and_justified(main_dir: Direction) -> Self {
Self {
main_dir,
@ -242,10 +251,12 @@ impl Layout {
Self::left_to_right().with_cross_align(cross_align)
}
#[inline(always)]
pub fn with_main_wrap(self, main_wrap: bool) -> Self {
Self { main_wrap, ..self }
}
#[inline(always)]
pub fn with_cross_align(self, cross_align: Align) -> Self {
Self {
cross_align,
@ -253,6 +264,7 @@ impl Layout {
}
}
#[inline(always)]
pub fn with_cross_justify(self, cross_justify: bool) -> Self {
Self {
cross_justify,
@ -263,26 +275,32 @@ impl Layout {
/// ## Inspectors
impl Layout {
#[inline(always)]
pub fn main_dir(&self) -> Direction {
self.main_dir
}
#[inline(always)]
pub fn main_wrap(&self) -> bool {
self.main_wrap
}
#[inline(always)]
pub fn cross_align(&self) -> Align {
self.cross_align
}
#[inline(always)]
pub fn cross_justify(&self) -> bool {
self.cross_justify
}
#[inline(always)]
pub fn is_horizontal(&self) -> bool {
self.main_dir().is_horizontal()
}
#[inline(always)]
pub fn is_vertical(&self) -> bool {
self.main_dir().is_vertical()
}

View file

@ -17,6 +17,7 @@ impl Placer {
}
}
#[inline(always)]
pub(crate) fn set_grid(&mut self, grid: grid::GridLayout) {
self.grid = Some(grid);
}
@ -27,38 +28,47 @@ impl Placer {
}
}
#[inline(always)]
pub(crate) fn grid(&self) -> Option<&grid::GridLayout> {
self.grid.as_ref()
}
#[inline(always)]
pub(crate) fn is_grid(&self) -> bool {
self.grid.is_some()
}
#[inline(always)]
pub(crate) fn layout(&self) -> &Layout {
&self.layout
}
#[inline(always)]
pub(crate) fn prefer_right_to_left(&self) -> bool {
self.layout.prefer_right_to_left()
}
#[inline(always)]
pub(crate) fn min_rect(&self) -> Rect {
self.region.min_rect
}
#[inline(always)]
pub(crate) fn max_rect(&self) -> Rect {
self.region.max_rect
}
#[inline(always)]
pub(crate) fn max_rect_finite(&self) -> Rect {
self.region.max_rect_finite()
}
#[inline(always)]
pub(crate) fn force_set_min_rect(&mut self, min_rect: Rect) {
self.region.min_rect = min_rect;
}
#[inline(always)]
pub(crate) fn cursor(&self) -> Rect {
self.region.cursor
}

View file

@ -689,6 +689,7 @@ impl Ui {
/// If the contents overflow, more space will be allocated.
/// When finished, the amount of space actually used (`min_rect`) will be allocated.
/// So you can request a lot of space and then use less.
#[inline(always)]
pub fn allocate_ui<R>(
&mut self,
desired_size: Vec2,
@ -701,11 +702,21 @@ impl Ui {
/// If the contents overflow, more space will be allocated.
/// When finished, the amount of space actually used (`min_rect`) will be allocated.
/// So you can request a lot of space and then use less.
#[inline(always)]
pub fn allocate_ui_with_layout<R>(
&mut self,
desired_size: Vec2,
layout: Layout,
add_contents: impl FnOnce(&mut Self) -> R,
) -> InnerResponse<R> {
self.allocate_ui_with_layout_dyn(desired_size, layout, Box::new(add_contents))
}
fn allocate_ui_with_layout_dyn<'c, R>(
&mut self,
desired_size: Vec2,
layout: Layout,
add_contents: Box<dyn FnOnce(&mut Self) -> R + 'c>,
) -> InnerResponse<R> {
debug_assert!(desired_size.x >= 0.0 && desired_size.y >= 0.0);
let item_spacing = self.spacing().item_spacing;
@ -798,6 +809,7 @@ impl Ui {
/// let response = ui.add(egui::Slider::new(&mut my_value, 0..=100));
/// response.on_hover_text("Drag me!");
/// ```
#[inline(always)]
pub fn add(&mut self, widget: impl Widget) -> Response {
widget.ui(self)
}
@ -835,6 +847,7 @@ impl Ui {
/// This will be in addition to the [`Spacing::item_spacing`}.
///
/// [`Self::min_rect`] will expand to contain the space.
#[inline(always)]
pub fn add_space(&mut self, amount: f32) {
self.placer.advance_cursor(amount);
}
@ -847,8 +860,9 @@ impl Ui {
/// Shortcut for `add(Label::new(text))`
///
/// See also [`Label`].
#[inline(always)]
pub fn label(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into())
label.into().ui(self)
}
/// Shortcut for `add(Label::new(text).text_color(color))`
@ -857,36 +871,36 @@ impl Ui {
color: impl Into<Color32>,
label: impl Into<Label>,
) -> Response {
self.add(label.into().text_color(color))
label.into().text_color(color).ui(self)
}
/// Shortcut for `add(Label::new(text).heading())`
pub fn heading(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into().heading())
label.into().heading().ui(self)
}
/// Shortcut for `add(Label::new(text).monospace())`
pub fn monospace(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into().monospace())
label.into().monospace().ui(self)
}
/// Show text as monospace with a gray background.
///
/// Shortcut for `add(Label::new(text).code())`
pub fn code(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into().code())
label.into().code().ui(self)
}
/// Shortcut for `add(Label::new(text).small())`
pub fn small(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into().small())
label.into().small().ui(self)
}
/// Shortcut for `add(Hyperlink::new(url))`
///
/// See also [`Hyperlink`].
pub fn hyperlink(&mut self, url: impl Into<String>) -> Response {
self.add(Hyperlink::new(url))
Hyperlink::new(url).ui(self)
}
/// Shortcut for `add(Hyperlink::new(url).text(label))`
@ -898,7 +912,7 @@ impl Ui {
///
/// See also [`Hyperlink`].
pub fn hyperlink_to(&mut self, label: impl Into<String>, url: impl Into<String>) -> Response {
self.add(Hyperlink::new(url).text(label))
Hyperlink::new(url).text(label).ui(self)
}
#[deprecated = "Use `text_edit_singleline` or `text_edit_multiline`"]
@ -910,14 +924,14 @@ impl Ui {
///
/// See also [`TextEdit`].
pub fn text_edit_singleline(&mut self, text: &mut String) -> Response {
self.add(TextEdit::singleline(text))
TextEdit::singleline(text).ui(self)
}
/// A `TextEdit` for multiple lines. Pressing enter key will create a new line.
///
/// See also [`TextEdit`].
pub fn text_edit_multiline(&mut self, text: &mut String) -> Response {
self.add(TextEdit::multiline(text))
TextEdit::multiline(text).ui(self)
}
/// Usage: `if ui.button("Click me").clicked() { … }`
@ -926,8 +940,9 @@ impl Ui {
///
/// See also [`Button`].
#[must_use = "You should check if the user clicked this with `if ui.button(…).clicked() { … } "]
#[inline(always)]
pub fn button(&mut self, text: impl Into<String>) -> Response {
self.add(Button::new(text))
Button::new(text).ui(self)
}
/// A button as small as normal body text.
@ -937,19 +952,19 @@ impl Ui {
/// Shortcut for `add(Button::new(text).small())`
#[must_use = "You should check if the user clicked this with `if ui.small_button(…).clicked() { … } "]
pub fn small_button(&mut self, text: impl Into<String>) -> Response {
self.add(Button::new(text).small())
Button::new(text).small().ui(self)
}
/// Show a checkbox.
pub fn checkbox(&mut self, checked: &mut bool, text: impl Into<String>) -> Response {
self.add(Checkbox::new(checked, text))
Checkbox::new(checked, text).ui(self)
}
/// Show a [`RadioButton`].
/// Often you want to use [`Self::radio_value`] instead.
#[must_use = "You should check if the user clicked this with `if ui.radio(…).clicked() { … } "]
pub fn radio(&mut self, selected: bool, text: impl Into<String>) -> Response {
self.add(RadioButton::new(selected, text))
RadioButton::new(selected, text).ui(self)
}
/// Show a [`RadioButton`]. It is selected if `*current_value == selected_value`.
@ -988,7 +1003,7 @@ impl Ui {
/// See also [`SelectableLabel`].
#[must_use = "You should check if the user clicked this with `if ui.selectable_label(…).clicked() { … } "]
pub fn selectable_label(&mut self, checked: bool, text: impl Into<String>) -> Response {
self.add(SelectableLabel::new(checked, text))
SelectableLabel::new(checked, text).ui(self)
}
/// Show selectable text. It is selected if `*current_value == selected_value`.
@ -1012,8 +1027,9 @@ impl Ui {
}
/// Shortcut for `add(Separator::default())` (see [`Separator`]).
#[inline(always)]
pub fn separator(&mut self) -> Response {
self.add(Separator::default())
Separator::default().ui(self)
}
/// Modify an angle. The given angle should be in radians, but is shown to the user in degrees.
@ -1058,8 +1074,9 @@ impl Ui {
/// Show an image here with the given size.
///
/// See also [`Image`].
#[inline(always)]
pub fn image(&mut self, texture_id: TextureId, size: impl Into<Vec2>) -> Response {
self.add(Image::new(texture_id, size))
Image::new(texture_id, size).ui(self)
}
}
@ -1202,10 +1219,19 @@ impl Ui {
}
/// Create a child ui which is indented to the right.
#[inline(always)]
pub fn indent<R>(
&mut self,
id_source: impl Hash,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
self.indent_dyn(id_source, Box::new(add_contents))
}
fn indent_dyn<'c, R>(
&mut self,
id_source: impl Hash,
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
) -> InnerResponse<R> {
assert!(
self.layout().is_vertical(),
@ -1266,6 +1292,7 @@ impl Ui {
/// ui.label("row");
/// });
/// ```
#[inline(always)]
pub fn horizontal<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
self.horizontal_with_main_wrap(false, add_contents)
}
@ -1336,10 +1363,19 @@ impl Ui {
})
}
#[inline(always)]
fn horizontal_with_main_wrap<R>(
&mut self,
main_wrap: bool,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
self.horizontal_with_main_wrap_dyn(main_wrap, Box::new(add_contents))
}
fn horizontal_with_main_wrap_dyn<'c, R>(
&mut self,
main_wrap: bool,
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
) -> InnerResponse<R> {
let initial_size = vec2(
self.available_size_before_wrap_finite().x,
@ -1353,7 +1389,7 @@ impl Ui {
}
.with_main_wrap(main_wrap);
self.allocate_ui_with_layout(initial_size, layout, add_contents)
self.allocate_ui_with_layout_dyn(initial_size, layout, add_contents)
}
/// Start a ui with vertical layout.
@ -1366,6 +1402,7 @@ impl Ui {
/// ui.label("under");
/// });
/// ```
#[inline(always)]
pub fn vertical<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
self.with_layout(Layout::top_down(Align::Min), add_contents)
}
@ -1415,6 +1452,14 @@ impl Ui {
&mut self,
layout: Layout,
add_contents: impl FnOnce(&mut Self) -> R,
) -> InnerResponse<R> {
self.with_layout_dyn(layout, Box::new(add_contents))
}
fn with_layout_dyn<'c, R>(
&mut self,
layout: Layout,
add_contents: Box<dyn FnOnce(&mut Self) -> R + 'c>,
) -> InnerResponse<R> {
let mut child_ui = self.child_ui(self.available_rect_before_wrap(), layout);
let inner = add_contents(&mut child_ui);

View file

@ -45,6 +45,7 @@ impl Align {
}
/// Convert `Min => 0.0`, `Center => 0.5` or `Max => 1.0`.
#[inline(always)]
pub fn to_factor(&self) -> f32 {
match self {
Self::Min => 0.0,
@ -54,6 +55,7 @@ impl Align {
}
/// Convert `Min => -1.0`, `Center => 0.0` or `Max => 1.0`.
#[inline(always)]
pub fn to_sign(&self) -> f32 {
match self {
Self::Min => -1.0,
@ -64,6 +66,7 @@ impl Align {
}
impl Default for Align {
#[inline(always)]
fn default() -> Align {
Align::Min
}
@ -90,9 +93,12 @@ impl Align2 {
}
impl Align2 {
#[inline(always)]
pub fn x(self) -> Align {
self.0[0]
}
#[inline(always)]
pub fn y(self) -> Align {
self.0[1]
}