From b29de28d1f0f608f8029c93d154cfd1b0f8b8cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 4 Feb 2023 07:33:33 +0100 Subject: [PATCH] Overhaul `Font` type to allow font family selection --- core/src/font.rs | 57 +++++------ examples/todos/fonts/icons.ttf | Bin 5596 -> 5732 bytes examples/todos/src/main.rs | 5 +- graphics/fonts/Lato-Regular.ttf | Bin 75136 -> 0 bytes graphics/fonts/OFL.txt | 93 ------------------ graphics/src/backend.rs | 3 + graphics/src/layer.rs | 2 +- graphics/src/renderer.rs | 4 + graphics/src/widget/canvas/text.rs | 2 +- native/src/overlay/menu.rs | 12 +-- native/src/renderer/null.rs | 8 +- native/src/text.rs | 5 +- native/src/widget/checkbox.rs | 13 +-- native/src/widget/pick_list.rs | 25 ++--- native/src/widget/radio.rs | 11 ++- native/src/widget/text.rs | 20 ++-- native/src/widget/text_input.rs | 39 ++++---- native/src/widget/toggler.rs | 13 +-- src/application.rs | 1 - src/settings.rs | 18 +--- .../Icons.ttf => wgpu/fonts/Iced-Icons.ttf | Bin 5032 -> 5108 bytes wgpu/src/backend.rs | 21 ++-- wgpu/src/lib.rs | 4 +- wgpu/src/settings.rs | 37 ++----- wgpu/src/text.rs | 10 +- 25 files changed, 147 insertions(+), 256 deletions(-) delete mode 100644 graphics/fonts/Lato-Regular.ttf delete mode 100644 graphics/fonts/OFL.txt rename graphics/fonts/Icons.ttf => wgpu/fonts/Iced-Icons.ttf (62%) diff --git a/core/src/font.rs b/core/src/font.rs index 130e378e..1f774a70 100644 --- a/core/src/font.rs +++ b/core/src/font.rs @@ -1,40 +1,29 @@ -use std::hash::{Hash, Hasher}; +use std::hash::Hash; /// A font. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Font { - /// The default font. - /// - /// This is normally a font configured in a renderer or loaded from the - /// system. - Default, + /// The name of a font family of choice. + Name(&'static str), - /// An external font. - External { - /// The name of the external font - name: &'static str, + /// Serif fonts represent the formal text style for a script. + Serif, - /// The bytes of the external font - bytes: &'static [u8], - }, -} - -impl Default for Font { - fn default() -> Font { - Font::Default - } -} - -impl Hash for Font { - fn hash(&self, hasher: &mut H) { - match self { - Self::Default => { - 0.hash(hasher); - } - Self::External { name, .. } => { - 1.hash(hasher); - name.hash(hasher); - } - } - } + /// Glyphs in sans-serif fonts, as the term is used in CSS, are generally low + /// contrast and have stroke endings that are plain — without any flaring, + /// cross stroke, or other ornamentation. + SansSerif, + + /// Glyphs in cursive fonts generally use a more informal script style, and + /// the result looks more like handwritten pen or brush writing than printed + /// letterwork. + Cursive, + + /// Fantasy fonts are primarily decorative or expressive fonts that contain + /// decorative or expressive representations of characters. + Fantasy, + + /// The sole criterion of a monospace font is that all glyphs have the same + /// fixed width. + Monospace, } diff --git a/examples/todos/fonts/icons.ttf b/examples/todos/fonts/icons.ttf index 4498299db26811ff8490001ea6f681529a4118f4..7b65fd3634a48b1afc3bebe7b3bb83a6c4f508d7 100644 GIT binary patch delta 1263 zcmcbk{Y0mpfsuiML4c8gfrWv=%`L=t=DEeI7#PGn7#J92++AGV7}Oag7#PGf7#J87 z{Dbw4+;l>i7#J8k7#JABl5-OaJ_$X0%)r3-gMooDD7maef$i#l76t}>7m)h2g7n<3 zi4!6j7?^z+7`O}46N?K#wlOe>DKIcFaHQu{)~8Lgjge+x;4fidV7icznwTPUR@aV! zfsu!Sfx#>zBQ=rj7jpyy10%>lm5khy3jTHm7X}8#2Mi1h5;^(FiHr*vo-i=*r!X)u z@Z}~}6fm+d3NSD*W`G=!mzbNXJhd#6fkDWHfq{8uL4I+`iex{31_n`(e!GGqi`0Ur zj@o+|82I)uFfg=%LxYilVT=8)3-SCmUm4_?UobE*Fx>oT#|EMwFt47@!0>+~^U}$7 zZ1Uzy!RkR0Fw6!PVPlA4U+Mpr1Cg+YLEGL+5Az|FV^%4TB_V0;B- zb1`T$1w+}~48lyyL4IW6WME*(0{K3UfsuuifssLhVG&e5cV(lb!7QUJL~0qi0Lu!|I|6ijrDbd3y*j1m4p zSOPK^1NM$HuC}zk6dq9D~5bS7%u+*aB%=|nBLp=k8xx|Olg?gFVo G$+rOO&e^B{ delta 1080 zcmaE&b4RU=R&qU|?ut zU@s0` zLqYOz%mPvm#)1qC%#l!W3x+3*>CgaRVTb|yoPmLfL54wxp_qYzA(Oj+VX~u;NIl3$ zAU&WkGld$?#K6vA3uQAia4@()*(?kk3_egcD+4z}2$apnz`+m?WpgoTGo(Y=+zi4D zlR&;@;bdT7$YNLuWiv7eF!Dp#ehf?ue2nrC4g)iT0HZFH&B7qSXbWYtGKewyLfLE# z0*uK}HWxz}V=^av1U%f*4X6(iut_au^aB ziWtyk(fMHvsSHI7#SEEXQxq5s8T1$o&~;6g6%C)fNK}3DeNiQK7DgsUW=0l9RtBd0 mY}S&Z#NrILg4Dd^%p6cWf#Qqt|9=Ml$u9f~n|+vna03AC=C$hp diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 6408f09c..5509cf0e 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -466,10 +466,7 @@ fn empty_message(message: &str) -> Element<'_, Message> { } // Fonts -const ICONS: Font = Font::External { - name: "Icons", - bytes: include_bytes!("../../todos/fonts/icons.ttf"), -}; +const ICONS: Font = Font::Name("Iced-Todos-Icons"); fn icon(unicode: char) -> Text<'static> { text(unicode.to_string()) diff --git a/graphics/fonts/Lato-Regular.ttf b/graphics/fonts/Lato-Regular.ttf deleted file mode 100644 index 33eba8b192384487f04951539f13bf1f8dd9f9cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75136 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 N02;dkxgR_y0RV`u8&v=R diff --git a/graphics/fonts/OFL.txt b/graphics/fonts/OFL.txt deleted file mode 100644 index dfca0da4..00000000 --- a/graphics/fonts/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato" - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs index 256b7ab5..7bbdee95 100644 --- a/graphics/src/backend.rs +++ b/graphics/src/backend.rs @@ -31,6 +31,9 @@ pub trait Text { /// [`ICON_FONT`]: Self::ICON_FONT const ARROW_DOWN_ICON: char; + /// Returns the default [`Font`]. + fn default_font(&self) -> Font; + /// Returns the default size of text. fn default_size(&self) -> f32; diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs index cc8f299c..f6eb2fdd 100644 --- a/graphics/src/layer.rs +++ b/graphics/src/layer.rs @@ -63,7 +63,7 @@ impl<'a> Layer<'a> { ), color: Color::new(0.9, 0.9, 0.9, 1.0), size: 20.0, - font: Font::Default, + font: Font::Monospace, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, }; diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 34b6eb1d..7ad53dec 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -130,6 +130,10 @@ where const CHECKMARK_ICON: char = B::CHECKMARK_ICON; const ARROW_DOWN_ICON: char = B::ARROW_DOWN_ICON; + fn default_font(&self) -> Self::Font { + self.backend().default_font() + } + fn default_size(&self) -> f32 { self.backend().default_size() } diff --git a/graphics/src/widget/canvas/text.rs b/graphics/src/widget/canvas/text.rs index 056f8204..8c0b2dfb 100644 --- a/graphics/src/widget/canvas/text.rs +++ b/graphics/src/widget/canvas/text.rs @@ -34,7 +34,7 @@ impl Default for Text { position: Point::ORIGIN, color: Color::BLACK, size: 16.0, - font: Font::Default, + font: Font::SansSerif, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, } diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs index 50f741ef..9c3a8a44 100644 --- a/native/src/overlay/menu.rs +++ b/native/src/overlay/menu.rs @@ -31,7 +31,7 @@ where width: f32, padding: Padding, text_size: Option, - font: Renderer::Font, + font: Option, style: ::Style, } @@ -58,7 +58,7 @@ where width: 0.0, padding: Padding::ZERO, text_size: None, - font: Default::default(), + font: None, style: Default::default(), } } @@ -82,8 +82,8 @@ where } /// Sets the font of the [`Menu`]. - pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; + pub fn font(mut self, font: impl Into) -> Self { + self.font = Some(font.into()); self } @@ -311,7 +311,7 @@ where last_selection: &'a mut Option, padding: Padding, text_size: Option, - font: Renderer::Font, + font: Option, style: ::Style, } @@ -491,7 +491,7 @@ where ..bounds }, size: text_size, - font: self.font.clone(), + font: self.font.unwrap_or_else(|| renderer.default_font()), color: if is_selected { appearance.selected_text_color } else { diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index 9376d540..50d7d6d6 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -40,12 +40,16 @@ impl Renderer for Null { impl text::Renderer for Null { type Font = Font; - const ICON_FONT: Font = Font::Default; + const ICON_FONT: Font = Font::SansSerif; const CHECKMARK_ICON: char = '0'; const ARROW_DOWN_ICON: char = '0'; + fn default_font(&self) -> Self::Font { + Font::SansSerif + } + fn default_size(&self) -> f32 { - 20.0 + 16.0 } fn measure( diff --git a/native/src/text.rs b/native/src/text.rs index 55c3cfd3..b7915a55 100644 --- a/native/src/text.rs +++ b/native/src/text.rs @@ -57,7 +57,7 @@ impl Hit { /// A renderer capable of measuring and drawing [`Text`]. pub trait Renderer: crate::Renderer { /// The font type used. - type Font: Default + Clone; + type Font: Copy; /// The icon font of the backend. const ICON_FONT: Self::Font; @@ -72,6 +72,9 @@ pub trait Renderer: crate::Renderer { /// [`ICON_FONT`]: Self::ICON_FONT const ARROW_DOWN_ICON: char; + /// Returns the default [`Font`]. + fn default_font(&self) -> Self::Font; + /// Returns the default size of [`Text`]. fn default_size(&self) -> f32; diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 9b69e574..138c458c 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -55,7 +55,7 @@ where size: f32, spacing: f32, text_size: Option, - font: Renderer::Font, + font: Option, icon: Icon, style: ::Style, } @@ -91,7 +91,7 @@ where size: Self::DEFAULT_SIZE, spacing: Self::DEFAULT_SPACING, text_size: None, - font: Renderer::Font::default(), + font: None, icon: Icon { font: Renderer::ICON_FONT, code_point: Renderer::CHECKMARK_ICON, @@ -128,8 +128,8 @@ where /// Sets the [`Font`] of the text of the [`Checkbox`]. /// /// [`Font`]: crate::text::Renderer::Font - pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; + pub fn font(mut self, font: impl Into) -> Self { + self.font = Some(font.into()); self } @@ -175,7 +175,7 @@ where .push(Row::new().width(self.size).height(self.size)) .push( Text::new(&self.label) - .font(self.font.clone()) + .font(self.font.unwrap_or_else(|| renderer.default_font())) .width(self.width) .size( self.text_size @@ -288,6 +288,7 @@ where { let label_layout = children.next().unwrap(); + let font = self.font.unwrap_or_else(|| renderer.default_font()); widget::text::draw( renderer, @@ -295,7 +296,7 @@ where label_layout, &self.label, self.text_size, - self.font.clone(), + font, widget::text::Appearance { color: custom_style.text_color, }, diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index a128d1ae..c1ff0004 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -35,7 +35,7 @@ where width: Length, padding: Padding, text_size: Option, - font: Renderer::Font, + font: Option, handle: Handle, style: ::Style, } @@ -70,7 +70,7 @@ where width: Length::Shrink, padding: Self::DEFAULT_PADDING, text_size: None, - font: Default::default(), + font: None, handle: Default::default(), style: Default::default(), } @@ -101,8 +101,8 @@ where } /// Sets the font of the [`PickList`]. - pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; + pub fn font(mut self, font: impl Into) -> Self { + self.font = Some(font.into()); self } @@ -163,7 +163,7 @@ where self.width, self.padding, self.text_size, - &self.font, + self.font.unwrap_or_else(|| renderer.default_font()), self.placeholder.as_deref(), &self.options, ) @@ -212,6 +212,7 @@ where cursor_position: Point, _viewport: &Rectangle, ) { + let font = self.font.unwrap_or_else(|| renderer.default_font()); draw( renderer, theme, @@ -219,7 +220,7 @@ where cursor_position, self.padding, self.text_size, - &self.font, + font, self.placeholder.as_deref(), self.selected.as_ref(), &self.handle, @@ -232,7 +233,7 @@ where &'b mut self, tree: &'b mut Tree, layout: Layout<'_>, - _renderer: &Renderer, + renderer: &Renderer, ) -> Option> { let state = tree.state.downcast_mut::>(); @@ -241,7 +242,7 @@ where state, self.padding, self.text_size, - self.font.clone(), + self.font.unwrap_or_else(|| renderer.default_font()), &self.options, self.style.clone(), ) @@ -343,7 +344,7 @@ pub fn layout( width: Length, padding: Padding, text_size: Option, - font: &Renderer::Font, + font: Renderer::Font, placeholder: Option<&str>, options: &[T], ) -> layout::Node @@ -362,7 +363,7 @@ where let (width, _) = renderer.measure( label, text_size, - font.clone(), + font, Size::new(f32::INFINITY, f32::INFINITY), ); @@ -560,7 +561,7 @@ pub fn draw<'a, T, Renderer>( cursor_position: Point, padding: Padding, text_size: Option, - font: &Renderer::Font, + font: Renderer::Font, placeholder: Option<&str>, selected: Option<&T>, handle: &Handle, @@ -637,7 +638,7 @@ pub fn draw<'a, T, Renderer>( renderer.fill_text(Text { content: label, size: text_size, - font: font.clone(), + font, color: if is_selected { style.text_color } else { diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 9daddfbc..bd803910 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -53,7 +53,7 @@ where size: f32, spacing: f32, text_size: Option, - font: Renderer::Font, + font: Option, style: ::Style, } @@ -95,7 +95,7 @@ where size: Self::DEFAULT_SIZE, spacing: Self::DEFAULT_SPACING, //15 text_size: None, - font: Default::default(), + font: None, style: Default::default(), } } @@ -125,8 +125,8 @@ where } /// Sets the text font of the [`Radio`] button. - pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; + pub fn font(mut self, font: impl Into) -> Self { + self.font = Some(font.into()); self } @@ -268,6 +268,7 @@ where { let label_layout = children.next().unwrap(); + let font = self.font.unwrap_or(renderer.default_font()); widget::text::draw( renderer, @@ -275,7 +276,7 @@ where label_layout, &self.label, self.text_size, - self.font.clone(), + font, widget::text::Appearance { color: custom_style.text_color, }, diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 3fee48f2..235a027e 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -37,7 +37,7 @@ where height: Length, horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, - font: Renderer::Font, + font: Option, style: ::Style, } @@ -51,7 +51,7 @@ where Text { content: content.into(), size: None, - font: Default::default(), + font: None, width: Length::Shrink, height: Length::Shrink, horizontal_alignment: alignment::Horizontal::Left, @@ -70,7 +70,7 @@ where /// /// [`Font`]: crate::text::Renderer::Font pub fn font(mut self, font: impl Into) -> Self { - self.font = font.into(); + self.font = Some(font.into()); self } @@ -138,8 +138,12 @@ where let bounds = limits.max(); - let (width, height) = - renderer.measure(&self.content, size, self.font.clone(), bounds); + let (width, height) = renderer.measure( + &self.content, + size, + self.font.unwrap_or_else(|| renderer.default_font()), + bounds, + ); let size = limits.resolve(Size::new(width, height)); @@ -156,13 +160,15 @@ where _cursor_position: Point, _viewport: &Rectangle, ) { + let font = self.font.unwrap_or_else(|| renderer.default_font()); + draw( renderer, style, layout, &self.content, self.size, - self.font.clone(), + font, theme.appearance(self.style), self.horizontal_alignment, self.vertical_alignment, @@ -242,7 +248,7 @@ where height: self.height, horizontal_alignment: self.horizontal_alignment, vertical_alignment: self.vertical_alignment, - font: self.font.clone(), + font: self.font, style: self.style, } } diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 5e198b8f..e6b70db2 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -61,7 +61,7 @@ where placeholder: String, value: Value, is_secure: bool, - font: Renderer::Font, + font: Option, width: Length, padding: Padding, size: Option, @@ -92,7 +92,7 @@ where placeholder: String::from(placeholder), value: Value::new(value), is_secure: false, - font: Default::default(), + font: None, width: Length::Fill, padding: Padding::new(5.0), size: None, @@ -129,7 +129,7 @@ where /// /// [`Font`]: text::Renderer::Font pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; + self.font = Some(font); self } /// Sets the width of the [`TextInput`]. @@ -179,6 +179,8 @@ where cursor_position: Point, value: Option<&Value>, ) { + let font = self.font.unwrap_or(renderer.default_font()); + draw( renderer, theme, @@ -188,7 +190,7 @@ where value.unwrap_or(&self.value), &self.placeholder, self.size, - &self.font, + font, self.is_secure, &self.style, ) @@ -258,7 +260,7 @@ where shell, &mut self.value, self.size, - &self.font, + self.font.unwrap_or(renderer.default_font()), self.is_secure, self.on_change.as_ref(), self.on_paste.as_deref(), @@ -277,6 +279,8 @@ where cursor_position: Point, _viewport: &Rectangle, ) { + let font = self.font.unwrap_or(renderer.default_font()); + draw( renderer, theme, @@ -286,7 +290,7 @@ where &self.value, &self.placeholder, self.size, - &self.font, + font, self.is_secure, &self.style, ) @@ -410,7 +414,7 @@ pub fn update<'a, Message, Renderer>( shell: &mut Shell<'_, Message>, value: &mut Value, size: Option, - font: &Renderer::Font, + font: Renderer::Font, is_secure: bool, on_change: &dyn Fn(String) -> Message, on_paste: Option<&dyn Fn(String) -> Message>, @@ -459,7 +463,7 @@ where find_cursor_position( renderer, text_layout.bounds(), - font.clone(), + font, size, &value, state, @@ -487,7 +491,7 @@ where let position = find_cursor_position( renderer, text_layout.bounds(), - font.clone(), + font, size, value, state, @@ -536,7 +540,7 @@ where let position = find_cursor_position( renderer, text_layout.bounds(), - font.clone(), + font, size, &value, state, @@ -816,7 +820,7 @@ pub fn draw( value: &Value, placeholder: &str, size: Option, - font: &Renderer::Font, + font: Renderer::Font, is_secure: bool, style: &::Style, ) where @@ -862,7 +866,7 @@ pub fn draw( value, size, position, - font.clone(), + font, ); let is_cursor_visible = ((focus.now - focus.updated_at) @@ -903,7 +907,7 @@ pub fn draw( value, size, left, - font.clone(), + font, ); let (right_position, right_offset) = @@ -913,7 +917,7 @@ pub fn draw( value, size, right, - font.clone(), + font, ); let width = right_position - left_position; @@ -948,7 +952,7 @@ pub fn draw( let text_width = renderer.measure_width( if text.is_empty() { placeholder } else { &text }, size, - font.clone(), + font, ); let render = |renderer: &mut Renderer| { @@ -963,7 +967,7 @@ pub fn draw( } else { theme.value_color(style) }, - font: font.clone(), + font: font, bounds: Rectangle { y: text_bounds.center_y(), width: f32::INFINITY, @@ -1195,8 +1199,7 @@ where { let size = size.unwrap_or_else(|| renderer.default_size()); - let offset = - offset(renderer, text_bounds, font.clone(), size, value, state); + let offset = offset(renderer, text_bounds, font, size, value, state); renderer .hit_test( diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index a434af65..495406db 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -42,7 +42,7 @@ where text_size: Option, text_alignment: alignment::Horizontal, spacing: f32, - font: Renderer::Font, + font: Option, style: ::Style, } @@ -79,7 +79,7 @@ where text_size: None, text_alignment: alignment::Horizontal::Left, spacing: 0.0, - font: Renderer::Font::default(), + font: None, style: Default::default(), } } @@ -117,8 +117,8 @@ where /// Sets the [`Font`] of the text of the [`Toggler`] /// /// [`Font`]: crate::text::Renderer::Font - pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; + pub fn font(mut self, font: impl Into) -> Self { + self.font = Some(font.into()); self } @@ -160,7 +160,7 @@ where row = row.push( Text::new(label) .horizontal_alignment(self.text_alignment) - .font(self.font.clone()) + .font(self.font.unwrap_or_else(|| renderer.default_font())) .width(self.width) .size( self.text_size @@ -236,6 +236,7 @@ where if let Some(label) = &self.label { let label_layout = children.next().unwrap(); + let font = self.font.unwrap_or_else(|| renderer.default_font()); crate::widget::text::draw( renderer, @@ -243,7 +244,7 @@ where label_layout, label, self.text_size, - self.font.clone(), + font, Default::default(), self.text_alignment, alignment::Vertical::Center, diff --git a/src/application.rs b/src/application.rs index 1db5c93f..9a1c1855 100644 --- a/src/application.rs +++ b/src/application.rs @@ -197,7 +197,6 @@ pub trait Application: Sized { let renderer_settings = crate::renderer::Settings { default_font: settings.default_font, default_text_size: settings.default_text_size, - text_multithreading: settings.text_multithreading, antialiasing: if settings.antialiasing { Some(crate::renderer::settings::Antialiasing::MSAAx4) } else { diff --git a/src/settings.rs b/src/settings.rs index 266ad404..ce07b0dd 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,5 +1,6 @@ //! Configure your application. use crate::window; +use crate::Font; /// The settings of an application. #[derive(Debug, Clone)] @@ -20,23 +21,16 @@ pub struct Settings { /// [`Application`]: crate::Application pub flags: Flags, - /// The bytes of the font that will be used by default. + /// The default [`Font`] to be used. /// - /// If `None` is provided, a default system font will be chosen. - // TODO: Add `name` for web compatibility - pub default_font: Option<&'static [u8]>, + /// By default, it uses [`Font::SansSerif`]. + pub default_font: Font, /// The text size that will be used by default. /// /// The default value is `16.0`. pub default_text_size: f32, - /// If enabled, spread text workload in multiple threads when multiple cores - /// are available. - /// - /// By default, it is disabled. - pub text_multithreading: bool, - /// If set to true, the renderer will try to perform antialiasing for some /// primitives. /// @@ -79,7 +73,6 @@ impl Settings { window: default_settings.window, default_font: default_settings.default_font, default_text_size: default_settings.default_text_size, - text_multithreading: default_settings.text_multithreading, antialiasing: default_settings.antialiasing, exit_on_close_request: default_settings.exit_on_close_request, try_opengles_first: default_settings.try_opengles_first, @@ -96,9 +89,8 @@ where id: None, window: Default::default(), flags: Default::default(), - default_font: Default::default(), + default_font: Font::SansSerif, default_text_size: 16.0, - text_multithreading: false, antialiasing: false, exit_on_close_request: true, try_opengles_first: false, diff --git a/graphics/fonts/Icons.ttf b/wgpu/fonts/Iced-Icons.ttf similarity index 62% rename from graphics/fonts/Icons.ttf rename to wgpu/fonts/Iced-Icons.ttf index 5e455b6988de00cc4a4e928aec96a27f555669a3..7112f08621071c423bf130f2906de1f878b6acbe 100644 GIT binary patch delta 1197 zcmZ3X{zbi>fsuiML4c8gfrWv=%`L=t);zyA3=G0I7#J92++AGV7}Oag7#M_iFfcGE z_y_A7*(n69VPIhFU|?VfOU_L!_@VoFGXn$T7X}7KujH~41-7gISr{1jEkNqi3et1C zCQgWCU|@D&VBjuDPb@9~*~Y*iyn%s%fg?SqvOdlI<+&OL2L2QV28II}sfj7Fvv0&Q zFfj5kFff>9WTYmt{bY_{U|@7%U|>+m$StYhj$m+MU|@W}z`!7qlb@W(puv#9z`!5D zz`($hn^;l6u#Ul-fq^jtM(d3St8r1DwOi!~k*xSR77(Vtuj*)5Fah*ne(eXV)_@2r=A)TVcwO17$NZa53zFvY8mz87@QF%nYiG>QFWd0~cd5 zl+DV(%?Jr~kiWPXS3t$N7_^zVp=@pjVWxOc7_e|MFfe3+LMM)ak%g0ikwJuE5mbVS zfsf%Zl+DcG#c&(SW?>Lv^o6on8N?X#plmh<5ynYSHWxz}<7OzEn?a4qd@?gzHY3C2 zI9Aho1_n=tWQJ6R6b1z_E1w|`6qlaKsVNGc$@zK33=BaGsSN21r3^U?i3~*y3_+>s zr8$X33=D1zAjKtMx`-j2A(cUa!H7YR!GJ-5!3t^|y1@_`69!!dBQUNvU@&4ZW?*p3 z&nt1uFG^2UFw!$nuu?$SuVAHMqHCmUWME`Wgj>THQW=UEiWxG&Zc|_|1iObJEVZaO zGe1wkP|pBih%SRCgGe%1VKD;($VOd=k0)Pb3uk1Qe3Vt2kzukryT;@XtRjV7vOCg@J*60s{ksLRvw3Zr8*Kkqiv%8yFb43(^yd z3m6y}1Q;0DI~W)kIMQ<})7)*(Suij#8!#|19LPvbtWS~XkkDjcVE(|sz+je31kY8Nl^J|(10|PtA1Lg%qsRd6Rwf8VE2rDo!Ftjl+ zhA}WOa4{G#*fB7GMh0cGd+=k11iJFzyemu$iTtC z$iM~@WsaQO!x$37z`(%Dz`(%Fz`&pb@&W?`V;tB(28IX*W-v>Kfti5|EY1Q}!^XhE zz{tS#g5d+t|NjgOFdA$y8`J_O1_nm9$%#z&Cl@fO=<|Rb3JNU{g9)Suf{`31<3TL)f&f`tJ_GrwS( z0SaxfDIf)m3=GUc|FakvK)3nT%@%pe&iYlsT4C@9uI_AxVvK~*!=Gq5p; zF%&Z}Fz9iE(g{eN5W_vFGy{Vv%+U;>@HK^sGcm9;*h1ON3>*wDP&Nw#2ZIlk&C0;d z5CUbhF>o-%L)lym+6?JXHaA1PFvBEJJg{&wFfe2>EQPWe83Y*lp=>4wK1O*co0&m? zQ5VW)VGv-ng|b;0#29^{Y&He~#$+g)iy@4$7|P~mP-8sloL^8`l$oAUqM+fdsbFL< zxlT~kC@nv)BsC`|KPWZ5G$*kL#)Z*gsYS(^`FRS4dIm6|$-KhalM{tSCNm3W*`_h% zGvqOpFr+f%Fyt`gGXycDGNdz-ql;}73ZHBxtUkG1SV^9l qk%^I+k%fUHCBHmRHzl)(DL)$&ON Self { - let text_pipeline = text::Pipeline::new( - device, - queue, - format, - settings.default_font, - settings.text_multithreading, - ); - + let text_pipeline = text::Pipeline::new(device, queue, format); let quad_pipeline = quad::Pipeline::new(device, format); let triangle_pipeline = triangle::Pipeline::new(device, format, settings.antialiasing); @@ -61,6 +55,7 @@ impl Backend { #[cfg(any(feature = "image", feature = "svg"))] image_pipeline, + default_font: settings.default_font, default_text_size: settings.default_text_size, } } @@ -199,9 +194,13 @@ impl iced_graphics::Backend for Backend { } impl backend::Text for Backend { - const ICON_FONT: Font = Font::Default; // TODO - const CHECKMARK_ICON: char = '✓'; - const ARROW_DOWN_ICON: char = '▼'; + const ICON_FONT: Font = Font::Name("Iced-Icons"); + const CHECKMARK_ICON: char = '\u{e800}'; + const ARROW_DOWN_ICON: char = '\u{f00c}'; + + fn default_font(&self) -> Font { + self.default_font + } fn default_size(&self) -> f32 { self.default_text_size diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 1a293681..6d6d3fd6 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -47,7 +47,9 @@ mod quad; mod text; mod triangle; -pub use iced_graphics::{Antialiasing, Color, Error, Primitive, Viewport}; +pub use iced_graphics::{ + Antialiasing, Color, Error, Font, Primitive, Viewport, +}; pub use iced_native::Theme; pub use wgpu; diff --git a/wgpu/src/settings.rs b/wgpu/src/settings.rs index 5ef79499..bd9cf473 100644 --- a/wgpu/src/settings.rs +++ b/wgpu/src/settings.rs @@ -1,12 +1,12 @@ //! Configure a renderer. -use std::fmt; - pub use crate::Antialiasing; +use crate::Font; + /// The settings of a [`Backend`]. /// /// [`Backend`]: crate::Backend -#[derive(Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Settings { /// The present mode of the [`Backend`]. /// @@ -16,42 +16,20 @@ pub struct Settings { /// The internal graphics backend to use. pub internal_backend: wgpu::Backends, - /// The bytes of the font that will be used by default. - /// - /// If `None` is provided, a default system font will be chosen. - pub default_font: Option<&'static [u8]>, + /// The default [`Font`] to use. + pub default_font: Font, /// The default size of text. /// /// By default, it will be set to `16.0`. pub default_text_size: f32, - /// If enabled, spread text workload in multiple threads when multiple cores - /// are available. - /// - /// By default, it is disabled. - pub text_multithreading: bool, - /// The antialiasing strategy that will be used for triangle primitives. /// /// By default, it is `None`. pub antialiasing: Option, } -impl fmt::Debug for Settings { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Settings") - .field("present_mode", &self.present_mode) - .field("internal_backend", &self.internal_backend) - // Instead of printing the font bytes, we simply show a `bool` indicating if using a default font or not. - .field("default_font", &self.default_font.is_some()) - .field("default_text_size", &self.default_text_size) - .field("text_multithreading", &self.text_multithreading) - .field("antialiasing", &self.antialiasing) - .finish() - } -} - impl Settings { /// Creates new [`Settings`] using environment configuration. /// @@ -81,9 +59,8 @@ impl Default for Settings { Settings { present_mode: wgpu::PresentMode::AutoVsync, internal_backend: wgpu::Backends::all(), - default_font: None, - default_text_size: 20.0, - text_multithreading: false, + default_font: Font::SansSerif, + default_text_size: 16.0, antialiasing: None, } } diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index fa7fd5df..083d9d2b 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -112,8 +112,6 @@ impl Pipeline { device: &wgpu::Device, queue: &wgpu::Queue, format: wgpu::TextureFormat, - _default_font: Option<&[u8]>, - _multithreading: bool, ) -> Self { Pipeline { renderers: Vec::new(), @@ -316,7 +314,11 @@ impl Pipeline { fn to_family(font: Font) -> glyphon::Family<'static> { match font { - Font::Default => glyphon::Family::SansSerif, - Font::External { name, .. } => glyphon::Family::Name(name), + Font::Name(name) => glyphon::Family::Name(name), + Font::SansSerif => glyphon::Family::SansSerif, + Font::Serif => glyphon::Family::Serif, + Font::Cursive => glyphon::Family::Cursive, + Font::Fantasy => glyphon::Family::Fantasy, + Font::Monospace => glyphon::Family::Monospace, } }