`Context::add_font` (#5228)
make it easier to add fonts. For example if I want to add a custom FontFamily or if the user wants to add a Chinese fallback * [x] I have followed the instructions in the PR template --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
d9a35a7289
commit
04ab5e7574
|
|
@ -9,7 +9,7 @@ use epaint::{
|
||||||
pos2,
|
pos2,
|
||||||
stats::PaintStats,
|
stats::PaintStats,
|
||||||
tessellator,
|
tessellator,
|
||||||
text::Fonts,
|
text::{FontInsert, FontPriority, Fonts},
|
||||||
util::OrderedFloat,
|
util::OrderedFloat,
|
||||||
vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, Rect,
|
vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, Rect,
|
||||||
TessellationOptions, TextureAtlas, TextureId, Vec2,
|
TessellationOptions, TextureAtlas, TextureId, Vec2,
|
||||||
|
|
@ -582,6 +582,28 @@ impl ContextImpl {
|
||||||
log::trace!("Loading new font definitions");
|
log::trace!("Loading new font definitions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.memory.add_fonts.is_empty() {
|
||||||
|
let fonts = self.memory.add_fonts.drain(..);
|
||||||
|
for font in fonts {
|
||||||
|
self.fonts.clear(); // recreate all the fonts
|
||||||
|
for family in font.families {
|
||||||
|
let fam = self
|
||||||
|
.font_definitions
|
||||||
|
.families
|
||||||
|
.entry(family.family)
|
||||||
|
.or_default();
|
||||||
|
match family.priority {
|
||||||
|
FontPriority::Highest => fam.insert(0, font.name.clone()),
|
||||||
|
FontPriority::Lowest => fam.push(font.name.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.font_definitions.font_data.insert(font.name, font.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
log::trace!("Adding new fonts");
|
||||||
|
}
|
||||||
|
|
||||||
let mut is_new = false;
|
let mut is_new = false;
|
||||||
|
|
||||||
let fonts = self
|
let fonts = self
|
||||||
|
|
@ -1727,6 +1749,7 @@ impl Context {
|
||||||
/// but you can call this to install additional fonts that support e.g. korean characters.
|
/// but you can call this to install additional fonts that support e.g. korean characters.
|
||||||
///
|
///
|
||||||
/// The new fonts will become active at the start of the next pass.
|
/// The new fonts will become active at the start of the next pass.
|
||||||
|
/// This will overwrite the existing fonts.
|
||||||
pub fn set_fonts(&self, font_definitions: FontDefinitions) {
|
pub fn set_fonts(&self, font_definitions: FontDefinitions) {
|
||||||
crate::profile_function!();
|
crate::profile_function!();
|
||||||
|
|
||||||
|
|
@ -1748,6 +1771,39 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tell `egui` which fonts to use.
|
||||||
|
///
|
||||||
|
/// The default `egui` fonts only support latin and cyrillic alphabets,
|
||||||
|
/// but you can call this to install additional fonts that support e.g. korean characters.
|
||||||
|
///
|
||||||
|
/// The new font will become active at the start of the next pass.
|
||||||
|
/// This will keep the existing fonts.
|
||||||
|
pub fn add_font(&self, new_font: FontInsert) {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
|
let pixels_per_point = self.pixels_per_point();
|
||||||
|
|
||||||
|
let mut update_fonts = true;
|
||||||
|
|
||||||
|
self.read(|ctx| {
|
||||||
|
if let Some(current_fonts) = ctx.fonts.get(&pixels_per_point.into()) {
|
||||||
|
if current_fonts
|
||||||
|
.lock()
|
||||||
|
.fonts
|
||||||
|
.definitions()
|
||||||
|
.font_data
|
||||||
|
.contains_key(&new_font.name)
|
||||||
|
{
|
||||||
|
update_fonts = false; // no need to update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if update_fonts {
|
||||||
|
self.memory_mut(|mem| mem.add_fonts.push(new_font));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Does the OS use dark or light mode?
|
/// Does the OS use dark or light mode?
|
||||||
/// This is used when the theme preference is set to [`crate::ThemePreference::System`].
|
/// This is used when the theme preference is set to [`crate::ThemePreference::System`].
|
||||||
pub fn system_theme(&self) -> Option<Theme> {
|
pub fn system_theme(&self) -> Option<Theme> {
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,10 @@ pub struct Memory {
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) new_font_definitions: Option<epaint::text::FontDefinitions>,
|
pub(crate) new_font_definitions: Option<epaint::text::FontDefinitions>,
|
||||||
|
|
||||||
|
/// add new font that will be applied at the start of the next frame
|
||||||
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
|
pub(crate) add_fonts: Vec<epaint::text::FontInsert>,
|
||||||
|
|
||||||
// Current active viewport
|
// Current active viewport
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) viewport_id: ViewportId,
|
pub(crate) viewport_id: ViewportId,
|
||||||
|
|
@ -119,6 +123,7 @@ impl Default for Memory {
|
||||||
layer_transforms: Default::default(),
|
layer_transforms: Default::default(),
|
||||||
popup: Default::default(),
|
popup: Default::default(),
|
||||||
everything_is_visible: Default::default(),
|
everything_is_visible: Default::default(),
|
||||||
|
add_fonts: Default::default(),
|
||||||
};
|
};
|
||||||
slf.interactions.entry(slf.viewport_id).or_default();
|
slf.interactions.entry(slf.viewport_id).or_default();
|
||||||
slf.areas.entry(slf.viewport_id).or_default();
|
slf.areas.entry(slf.viewport_id).or_default();
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,50 @@ pub struct FontDefinitions {
|
||||||
pub families: BTreeMap<FontFamily, Vec<String>>,
|
pub families: BTreeMap<FontFamily, Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FontInsert {
|
||||||
|
/// Font name
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
/// A `.ttf` or `.otf` file and a font face index.
|
||||||
|
pub data: FontData,
|
||||||
|
|
||||||
|
/// Sets the font family and priority
|
||||||
|
pub families: Vec<InsertFontFamily>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct InsertFontFamily {
|
||||||
|
/// Font family
|
||||||
|
pub family: FontFamily,
|
||||||
|
|
||||||
|
/// Fallback or Primary font
|
||||||
|
pub priority: FontPriority,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FontPriority {
|
||||||
|
/// Prefer this font before all existing ones.
|
||||||
|
///
|
||||||
|
/// If a desired glyph exists in this font, it will be used.
|
||||||
|
Highest,
|
||||||
|
|
||||||
|
/// Use this font as a fallback, after all existing ones.
|
||||||
|
///
|
||||||
|
/// This font will only be used if the glyph is not found in any of the previously installed fonts.
|
||||||
|
Lowest,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontInsert {
|
||||||
|
pub fn new(name: &str, data: FontData, families: Vec<InsertFontFamily>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_owned(),
|
||||||
|
data,
|
||||||
|
families,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for FontDefinitions {
|
impl Default for FontDefinitions {
|
||||||
/// Specifies the default fonts if the feature `default_fonts` is enabled,
|
/// Specifies the default fonts if the feature `default_fonts` is enabled,
|
||||||
/// otherwise this is the same as [`Self::empty`].
|
/// otherwise this is the same as [`Self::empty`].
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@ mod text_layout_types;
|
||||||
pub const TAB_SIZE: usize = 4;
|
pub const TAB_SIZE: usize = 4;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
fonts::{FontData, FontDefinitions, FontFamily, FontId, FontTweak, Fonts, FontsImpl},
|
fonts::{
|
||||||
|
FontData, FontDefinitions, FontFamily, FontId, FontInsert, FontPriority, FontTweak, Fonts,
|
||||||
|
FontsImpl, InsertFontFamily,
|
||||||
|
},
|
||||||
text_layout::layout,
|
text_layout::layout,
|
||||||
text_layout_types::*,
|
text_layout_types::*,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||||
|
|
||||||
use eframe::egui;
|
use eframe::{
|
||||||
|
egui,
|
||||||
|
epaint::text::{FontInsert, InsertFontFamily},
|
||||||
|
};
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||||
|
|
@ -16,7 +19,28 @@ fn main() -> eframe::Result {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_custom_fonts(ctx: &egui::Context) {
|
// Demonstrates how to add a font to the existing ones
|
||||||
|
fn add_font(ctx: &egui::Context) {
|
||||||
|
ctx.add_font(FontInsert::new(
|
||||||
|
"my_font",
|
||||||
|
egui::FontData::from_static(include_bytes!(
|
||||||
|
"../../../crates/epaint_default_fonts/fonts/Hack-Regular.ttf"
|
||||||
|
)),
|
||||||
|
vec![
|
||||||
|
InsertFontFamily {
|
||||||
|
family: egui::FontFamily::Proportional,
|
||||||
|
priority: egui::epaint::text::FontPriority::Highest,
|
||||||
|
},
|
||||||
|
InsertFontFamily {
|
||||||
|
family: egui::FontFamily::Monospace,
|
||||||
|
priority: egui::epaint::text::FontPriority::Lowest,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demonstrates how to replace all fonts.
|
||||||
|
fn replace_fonts(ctx: &egui::Context) {
|
||||||
// Start with the default fonts (we will be adding to them rather than replacing them).
|
// Start with the default fonts (we will be adding to them rather than replacing them).
|
||||||
let mut fonts = egui::FontDefinitions::default();
|
let mut fonts = egui::FontDefinitions::default();
|
||||||
|
|
||||||
|
|
@ -53,7 +77,8 @@ struct MyApp {
|
||||||
|
|
||||||
impl MyApp {
|
impl MyApp {
|
||||||
fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||||
setup_custom_fonts(&cc.egui_ctx);
|
replace_fonts(&cc.egui_ctx);
|
||||||
|
add_font(&cc.egui_ctx);
|
||||||
Self {
|
Self {
|
||||||
text: "Edit this text field if you want".to_owned(),
|
text: "Edit this text field if you want".to_owned(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue