Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Replace the current text rendering engine with fontdue. #28

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ include = [ "**/*.rs", "Cargo.toml", "fonts/ProggyClean.ttf", "fonts/Comfortaa-R
[dependencies]
ahash = { version = "0.4", features = ["std"], default-features = false }
parking_lot = "0.11"
rusttype = "0.9"
fontdue = { version = "0.3", git = "https://github.com/mooman219/fontdue" }
serde = { version = "1", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }

Expand Down
17 changes: 9 additions & 8 deletions egui/src/containers/collapsing_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,9 @@ struct Prepared {

impl CollapsingHeader {
fn begin(self, ui: &mut Ui) -> Prepared {
assert!(
ui.layout().dir() == Direction::Vertical,
assert_eq!(
ui.layout().dir(),
Direction::Vertical,
"Horizontal collapsing is unimplemented"
);
let Self {
Expand All @@ -186,22 +187,22 @@ impl CollapsingHeader {

let available = ui.available_finite();
let text_pos = available.min + vec2(ui.style().spacing.indent, 0.0);
let galley = label.layout_width(ui, available.right() - text_pos.x);
let text_max_x = text_pos.x + galley.size.x;
let layout = label.layout_width(ui, available.right() - text_pos.x);
let text_max_x = text_pos.x + layout.size.x;
let desired_width = text_max_x - available.left();
let desired_width = desired_width.max(available.width());

let mut desired_size = vec2(
desired_width,
galley.size.y + 2.0 * ui.style().spacing.button_padding.y,
layout.size.y + 2.0 * ui.style().spacing.button_padding.y,
);
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
let rect = ui.allocate_space(desired_size);

let header_response = ui.interact(rect, id, Sense::click());
let text_pos = pos2(
text_pos.x,
header_response.rect.center().y - galley.size.y / 2.0,
header_response.rect.center().y - layout.size.y / 2.0,
);

let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open);
Expand All @@ -226,9 +227,9 @@ impl CollapsingHeader {
}

let painter = ui.painter();
painter.galley(
painter.layout(
text_pos,
galley,
layout,
label.text_style_or_default(ui.style()),
ui.style().interact(&header_response).text_color(),
);
Expand Down
18 changes: 8 additions & 10 deletions egui/src/containers/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

use std::sync::Arc;

use crate::{paint::*, widgets::*, *};

use super::*;
use crate::{paint::fonts::GlyphLayout, paint::*, widgets::*, *};

/// Builder for a floating window which can be dragged, closed, collapsed, resized and scrolled (off by default).
///
Expand Down Expand Up @@ -219,7 +217,7 @@ impl<'open> Window<'open> {
// First interact (move etc) to avoid frame delay:
let last_frame_outer_rect = area.state().rect();
let interaction = if possible.movable || possible.resizable {
let title_bar_height = title_label.font_height(ctx.fonts(), &ctx.style())
let title_bar_height = title_label.font_height(&ctx.fonts().lock(), &ctx.style())
+ 1.0 * ctx.style().spacing.item_spacing.y; // this could be better
let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height);

Expand Down Expand Up @@ -599,7 +597,7 @@ fn paint_frame_interaction(

struct TitleBar {
title_label: Label,
title_galley: font::Galley,
title_layout: GlyphLayout,
title_rect: Rect,
rect: Rect,
}
Expand All @@ -613,7 +611,7 @@ fn show_title_bar(
collapsible: bool,
) -> TitleBar {
let (title_bar, response) = ui.horizontal(|ui| {
ui.set_min_height(title_label.font_height(ui.fonts(), ui.style()));
ui.set_min_height(title_label.font_height(&ui.fonts().lock(), ui.style()));

let item_spacing = ui.style().spacing.item_spacing;
let button_size = ui.style().spacing.icon_width;
Expand All @@ -630,8 +628,8 @@ fn show_title_bar(
collapsing_header::paint_icon(ui, openness, &collapse_button_response);
}

let title_galley = title_label.layout(ui);
let title_rect = ui.allocate_space(title_galley.size);
let title_layout = title_label.layout(ui);
let title_rect = ui.allocate_space(title_layout.size);

if show_close_button {
// Reserve space for close button which will be added later (once we know our full width):
Expand All @@ -649,7 +647,7 @@ fn show_title_bar(

TitleBar {
title_label,
title_galley,
title_layout,
title_rect,
rect: Rect::invalid(), // Will be filled in later
}
Expand Down Expand Up @@ -685,7 +683,7 @@ impl TitleBar {

// TODO: pick style for title based on move interaction
self.title_label
.paint_galley(ui, self.title_rect.min, self.title_galley);
.paint_layout(ui, self.title_rect.min, self.title_layout);

if let Some(content_response) = &content_response {
// paint separator between title and content:
Expand Down
35 changes: 19 additions & 16 deletions egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct Options {
/// Controls the tessellator.
paint_options: paint::PaintOptions,
/// Font sizes etc.
font_definitions: FontDefinitions,
font_configuration: FontConfiguration,
}

/// Thi is the first thing you need when working with Egui.
Expand All @@ -39,7 +39,7 @@ struct Options {
pub struct Context {
options: Mutex<Options>,
/// None until first call to `begin_frame`.
fonts: Option<Arc<Fonts>>,
fonts: Option<Arc<Mutex<Fonts>>>,
memory: Arc<Mutex<Memory>>,
animation_manager: Arc<Mutex<AnimationManager>>,

Expand Down Expand Up @@ -110,24 +110,24 @@ impl Context {

/// Not valid until first call to `begin_frame()`
/// That's because since we don't know the proper `pixels_per_point` until then.
pub fn fonts(&self) -> &Fonts {
&*self
.fonts
pub fn fonts(&self) -> Arc<Mutex<Fonts>> {
self.fonts
.as_ref()
.expect("No fonts available until first call to Context::begin_frame()`")
.clone()
}

/// The Egui texture, containing font characters etc..
/// Not valid until first call to `begin_frame()`
/// That's because since we don't know the proper `pixels_per_point` until then.
pub fn texture(&self) -> Arc<paint::Texture> {
self.fonts().texture()
self.fonts().lock().texture()
}

/// Will become active at the start of the next frame.
/// `pixels_per_point` will be ignored (overwritten at start of each frame with the contents of input)
pub fn set_fonts(&self, font_definitions: FontDefinitions) {
lock(&self.options, "options").font_definitions = font_definitions;
pub fn set_fonts(&self, font_configuration: FontConfiguration) {
lock(&self.options, "options").font_configuration = font_configuration;
}

pub fn style(&self) -> Arc<Style> {
Expand Down Expand Up @@ -183,14 +183,16 @@ impl Context {
self.used_ids.lock().clear();

self.input = std::mem::take(&mut self.input).begin_frame(new_raw_input);
let mut font_definitions = lock(&self.options, "options").font_definitions.clone();
font_definitions.pixels_per_point = self.input.pixels_per_point();
let mut font_configuration = lock(&self.options, "options").font_configuration.clone();
font_configuration.pixels_per_point = self.input.pixels_per_point();
let same_as_current = match &self.fonts {
None => false,
Some(fonts) => *fonts.definitions() == font_definitions,
Some(fonts) => *fonts.lock().configuration() == font_configuration,
};
if !same_as_current {
self.fonts = Some(Arc::new(Fonts::from_definitions(font_definitions)));
self.fonts = Some(Arc::new(Mutex::new(Fonts::from_definitions(
font_configuration,
))));
}
}

Expand Down Expand Up @@ -523,10 +525,11 @@ impl Context {
CollapsingHeader::new("Fonts")
.default_open(false)
.show(ui, |ui| {
let mut font_definitions = self.fonts().definitions().clone();
font_definitions.ui(ui);
self.fonts().texture().ui(ui);
self.set_fonts(font_definitions);
let mut font_configuration = self.fonts().lock().configuration().clone();
font_configuration.ui(ui);
let texture = self.fonts().lock().texture();
texture.ui(ui);
self.set_fonts(font_configuration);
});

CollapsingHeader::new("Painting")
Expand Down
2 changes: 1 addition & 1 deletion egui/src/demos/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl FrameHistory {
ui.fonts(),
pos2(rect.left(), y),
align::LEFT_BOTTOM,
text,
&text,
TextStyle::Monospace,
color::WHITE,
));
Expand Down
8 changes: 4 additions & 4 deletions egui/src/introspection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ impl Texture {
}
}

impl paint::FontDefinitions {
impl paint::FontConfiguration {
pub fn ui(&mut self, ui: &mut Ui) {
for (text_style, (_family, size)) in self.fonts.iter_mut() {
for (text_style, definition) in self.definitions.iter_mut() {
// TODO: radio button for family
ui.add(
Slider::f32(size, 4.0..=40.0)
Slider::f32(&mut definition.scale_in_points, 4.0..=40.0)
.precision(0)
.text(format!("{:?}", text_style)),
);
}
if ui.button("Reset fonts").clicked {
*self = paint::FontDefinitions::with_pixels_per_point(self.pixels_per_point);
*self = paint::FontConfiguration::with_pixels_per_point(self.pixels_per_point);
}
}
}
23 changes: 13 additions & 10 deletions egui/src/paint/command.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use std::sync::Arc;

use parking_lot::Mutex;

use {
super::{font::Galley, fonts::TextStyle, Fonts, Srgba, Triangles},
super::{fonts::TextStyle, Fonts, Srgba, Triangles},
crate::{
align::{anchor_rect, Align},
math::{Pos2, Rect},
paint::fonts::GlyphLayout,
},
};

Expand Down Expand Up @@ -38,9 +43,8 @@ pub enum PaintCmd {
Text {
/// Top left corner of the first character.
pos: Pos2,
/// The layed out text
galley: Galley,
text_style: TextStyle, // TODO: Font?
layout: GlyphLayout,
text_style: TextStyle,
color: Srgba,
},
Triangles(Triangles),
Expand Down Expand Up @@ -91,19 +95,18 @@ impl PaintCmd {
}

pub fn text(
fonts: &Fonts,
fonts: Arc<Mutex<Fonts>>,
pos: Pos2,
anchor: (Align, Align),
text: impl Into<String>,
text: &str,
text_style: TextStyle,
color: Srgba,
) -> Self {
let font = &fonts[text_style];
let galley = font.layout_multiline(text.into(), f32::INFINITY);
let rect = anchor_rect(Rect::from_min_size(pos, galley.size), anchor);
let layout = fonts.lock().layout_multiline(text_style, text, None);
let rect = anchor_rect(Rect::from_min_size(pos, layout.size), anchor);
Self::Text {
pos: rect.min,
galley,
layout,
text_style,
color,
}
Expand Down
Loading