Struct druid::text::FontDescriptor
source · pub struct FontDescriptor {
pub family: FontFamily,
pub size: f64,
pub weight: FontWeight,
pub style: FontStyle,
}
Expand description
A collection of attributes that describe a font.
This is provided as a convenience; library consumers may wish to have a single type that represents a specific font face at a specific size.
Fields§
§family: FontFamily
The font’s FontFamily
.
size: f64
The font’s size.
weight: FontWeight
The font’s FontWeight
.
style: FontStyle
The font’s FontStyle
.
Implementations§
source§impl FontDescriptor
impl FontDescriptor
sourcepub const fn new(family: FontFamily) -> Self
pub const fn new(family: FontFamily) -> Self
Create a new descriptor with the provided FontFamily
.
Examples found in repository?
examples/styled_text.rs (line 107)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
fn ui_builder() -> impl Widget<AppData> {
let my_painter = Painter::new(|ctx, _, _| {
let bounds = ctx.size().to_rect();
if ctx.is_hot() {
ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
}
if ctx.is_active() {
ctx.stroke(bounds, &Color::WHITE, 2.0);
}
});
// This is Druid's default text style.
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
// The text_color, text_size, and font builder methods can override the
// defaults provided by the theme by passing in a Key or a concrete value.
//
// In this example, text_color receives a Key from the theme, text_size
// gets a custom key which we set with the env_scope wrapper, and the
// default font key (theme::FONT_NAME) is overridden in the env_scope
// wrapper. (Like text_color and text_size, the font can be set using the
// with_font builder method, but overriding here makes it easy to fall back
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
.with_text_color(theme::PRIMARY_LIGHT)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});
let labels = Scroll::new(
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(label)
.with_default_spacer()
.with_child(styled_label),
)
.expand_height()
.fix_width(COLUMN_WIDTH);
let stepper = Stepper::new()
.with_range(0.0, 100.0)
.with_step(1.0)
.with_wraparound(false)
.lens(AppData::size);
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let stepper_textbox = LensWrap::new(
Parse::new(TextBox::new()),
AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
);
let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
let stepper_row = Flex::row()
.with_child(stepper_textbox)
.with_child(stepper)
.with_default_spacer()
.with_child(mono_checkbox);
let input = TextBox::multiline()
.with_placeholder("Your sample text here :)")
.fix_width(COLUMN_WIDTH)
.fix_height(140.0)
.lens(AppData::text);
Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
.with_default_spacer()
.with_flex_child(labels, 1.0)
.with_default_spacer()
.with_child(input)
.with_default_spacer()
.with_child(stepper_row)
.with_default_spacer()
}
More examples
examples/custom_widget.rs (line 119)
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
fn paint(&mut self, ctx: &mut PaintCtx, data: &String, env: &Env) {
// Clear the whole widget with the color of your choice
// (ctx.size() returns the size of the layout rect we're painting in)
// Note: ctx also has a `clear` method, but that clears the whole context,
// and we only want to clear this widget's area.
let size = ctx.size();
let rect = size.to_rect();
ctx.fill(rect, &Color::WHITE);
// We can paint with a Z index, this indicates that this code will be run
// after the rest of the painting. Painting with z-index is done in order,
// so first everything with z-index 1 is painted and then with z-index 2 etc.
// As you can see this(red) curve is drawn on top of the green curve
ctx.paint_with_z_index(1, move |ctx| {
let mut path = BezPath::new();
path.move_to((0.0, size.height));
path.quad_to((40.0, 50.0), (size.width, 0.0));
// Create a color
let stroke_color = Color::rgb8(128, 0, 0);
// Stroke the path with thickness 1.0
ctx.stroke(path, &stroke_color, 5.0);
});
// Create an arbitrary bezier path
let mut path = BezPath::new();
path.move_to(Point::ORIGIN);
path.quad_to((40.0, 50.0), (size.width, size.height));
// Create a color
let stroke_color = Color::rgb8(0, 128, 0);
// Stroke the path with thickness 5.0
ctx.stroke(path, &stroke_color, 5.0);
// Rectangles: the path for practical people
let rect = Rect::from_origin_size((10.0, 10.0), (100.0, 100.0));
// Note the Color:rgba8 which includes an alpha channel (7F in this case)
let fill_color = Color::rgba8(0x00, 0x00, 0x00, 0x7F);
ctx.fill(rect, &fill_color);
// Text is easy; in real use TextLayout should either be stored in the
// widget and reused, or a label child widget to manage it all.
// This is one way of doing it, you can also use a builder-style way.
let mut layout = TextLayout::<String>::from_text(data);
layout.set_font(FontDescriptor::new(FontFamily::SERIF).with_size(24.0));
layout.set_text_color(fill_color);
layout.rebuild_if_needed(ctx.text(), env);
// Let's rotate our text slightly. First we save our current (default) context:
ctx.with_save(|ctx| {
// Now we can rotate the context (or set a clip path, for instance):
// This makes it so that anything drawn after this (in the closure) is
// transformed.
// The transformation is in radians, but be aware it transforms the canvas,
// not just the part you are drawing. So we draw at (80.0, 40.0) on the rotated
// canvas, this is NOT the same position as (80.0, 40.0) on the original canvas.
ctx.transform(Affine::rotate(std::f64::consts::FRAC_PI_4));
layout.draw(ctx, (80.0, 40.0));
});
// When we exit with_save, the original context's rotation is restored
// This is the builder-style way of drawing text.
let text = ctx.text();
let layout = text
.new_text_layout(data.clone())
.font(FontFamily::SERIF, 24.0)
.text_color(Color::rgb8(128, 0, 0))
.build()
.unwrap();
ctx.draw_text(&layout, (100.0, 25.0));
// Let's burn some CPU to make a (partially transparent) image buffer
let image_data = make_image_data(256, 256);
let image = ctx
.make_image(256, 256, &image_data, ImageFormat::RgbaSeparate)
.unwrap();
// The image is automatically scaled to fit the rect you pass to draw_image
ctx.draw_image(&image, size.to_rect(), InterpolationMode::Bilinear);
}
sourcepub const fn with_size(self, size: f64) -> Self
pub const fn with_size(self, size: f64) -> Self
Buider-style method to set the descriptor’s font size.
Examples found in repository?
examples/event_viewer.rs (line 341)
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
pub fn main() {
//describe the main window
let main_window = WindowDesc::new(build_root_widget())
.title("Event Viewer")
.window_size((760.0, 680.0));
//start the application
AppLauncher::with_window(main_window)
.log_to_console()
.configure_env(|env, _| {
env.set(theme::UI_FONT, FontDescriptor::default().with_size(12.0));
env.set(theme::TEXT_COLOR, TEXT_COLOR);
env.set(theme::WIDGET_PADDING_HORIZONTAL, 2.0);
env.set(theme::WIDGET_PADDING_VERTICAL, 2.0);
})
.launch(AppState {
text_input: String::new(),
events: Arc::new(Vec::new()),
})
.expect("Failed to launch application");
}
More examples
examples/styled_text.rs (line 111)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
fn ui_builder() -> impl Widget<AppData> {
let my_painter = Painter::new(|ctx, _, _| {
let bounds = ctx.size().to_rect();
if ctx.is_hot() {
ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
}
if ctx.is_active() {
ctx.stroke(bounds, &Color::WHITE, 2.0);
}
});
// This is Druid's default text style.
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
// The text_color, text_size, and font builder methods can override the
// defaults provided by the theme by passing in a Key or a concrete value.
//
// In this example, text_color receives a Key from the theme, text_size
// gets a custom key which we set with the env_scope wrapper, and the
// default font key (theme::FONT_NAME) is overridden in the env_scope
// wrapper. (Like text_color and text_size, the font can be set using the
// with_font builder method, but overriding here makes it easy to fall back
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
.with_text_color(theme::PRIMARY_LIGHT)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});
let labels = Scroll::new(
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(label)
.with_default_spacer()
.with_child(styled_label),
)
.expand_height()
.fix_width(COLUMN_WIDTH);
let stepper = Stepper::new()
.with_range(0.0, 100.0)
.with_step(1.0)
.with_wraparound(false)
.lens(AppData::size);
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let stepper_textbox = LensWrap::new(
Parse::new(TextBox::new()),
AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
);
let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
let stepper_row = Flex::row()
.with_child(stepper_textbox)
.with_child(stepper)
.with_default_spacer()
.with_child(mono_checkbox);
let input = TextBox::multiline()
.with_placeholder("Your sample text here :)")
.fix_width(COLUMN_WIDTH)
.fix_height(140.0)
.lens(AppData::text);
Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
.with_default_spacer()
.with_flex_child(labels, 1.0)
.with_default_spacer()
.with_child(input)
.with_default_spacer()
.with_child(stepper_row)
.with_default_spacer()
}
examples/custom_widget.rs (line 119)
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
fn paint(&mut self, ctx: &mut PaintCtx, data: &String, env: &Env) {
// Clear the whole widget with the color of your choice
// (ctx.size() returns the size of the layout rect we're painting in)
// Note: ctx also has a `clear` method, but that clears the whole context,
// and we only want to clear this widget's area.
let size = ctx.size();
let rect = size.to_rect();
ctx.fill(rect, &Color::WHITE);
// We can paint with a Z index, this indicates that this code will be run
// after the rest of the painting. Painting with z-index is done in order,
// so first everything with z-index 1 is painted and then with z-index 2 etc.
// As you can see this(red) curve is drawn on top of the green curve
ctx.paint_with_z_index(1, move |ctx| {
let mut path = BezPath::new();
path.move_to((0.0, size.height));
path.quad_to((40.0, 50.0), (size.width, 0.0));
// Create a color
let stroke_color = Color::rgb8(128, 0, 0);
// Stroke the path with thickness 1.0
ctx.stroke(path, &stroke_color, 5.0);
});
// Create an arbitrary bezier path
let mut path = BezPath::new();
path.move_to(Point::ORIGIN);
path.quad_to((40.0, 50.0), (size.width, size.height));
// Create a color
let stroke_color = Color::rgb8(0, 128, 0);
// Stroke the path with thickness 5.0
ctx.stroke(path, &stroke_color, 5.0);
// Rectangles: the path for practical people
let rect = Rect::from_origin_size((10.0, 10.0), (100.0, 100.0));
// Note the Color:rgba8 which includes an alpha channel (7F in this case)
let fill_color = Color::rgba8(0x00, 0x00, 0x00, 0x7F);
ctx.fill(rect, &fill_color);
// Text is easy; in real use TextLayout should either be stored in the
// widget and reused, or a label child widget to manage it all.
// This is one way of doing it, you can also use a builder-style way.
let mut layout = TextLayout::<String>::from_text(data);
layout.set_font(FontDescriptor::new(FontFamily::SERIF).with_size(24.0));
layout.set_text_color(fill_color);
layout.rebuild_if_needed(ctx.text(), env);
// Let's rotate our text slightly. First we save our current (default) context:
ctx.with_save(|ctx| {
// Now we can rotate the context (or set a clip path, for instance):
// This makes it so that anything drawn after this (in the closure) is
// transformed.
// The transformation is in radians, but be aware it transforms the canvas,
// not just the part you are drawing. So we draw at (80.0, 40.0) on the rotated
// canvas, this is NOT the same position as (80.0, 40.0) on the original canvas.
ctx.transform(Affine::rotate(std::f64::consts::FRAC_PI_4));
layout.draw(ctx, (80.0, 40.0));
});
// When we exit with_save, the original context's rotation is restored
// This is the builder-style way of drawing text.
let text = ctx.text();
let layout = text
.new_text_layout(data.clone())
.font(FontFamily::SERIF, 24.0)
.text_color(Color::rgb8(128, 0, 0))
.build()
.unwrap();
ctx.draw_text(&layout, (100.0, 25.0));
// Let's burn some CPU to make a (partially transparent) image buffer
let image_data = make_image_data(256, 256);
let image = ctx
.make_image(256, 256, &image_data, ImageFormat::RgbaSeparate)
.unwrap();
// The image is automatically scaled to fit the rect you pass to draw_image
ctx.draw_image(&image, size.to_rect(), InterpolationMode::Bilinear);
}
sourcepub const fn with_weight(self, weight: FontWeight) -> Self
pub const fn with_weight(self, weight: FontWeight) -> Self
Buider-style method to set the descriptor’s FontWeight
.
sourcepub const fn with_style(self, style: FontStyle) -> Self
pub const fn with_style(self, style: FontStyle) -> Self
Buider-style method to set the descriptor’s FontStyle
.
Trait Implementations§
source§impl Clone for FontDescriptor
impl Clone for FontDescriptor
source§fn clone(&self) -> FontDescriptor
fn clone(&self) -> FontDescriptor
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read moresource§impl Data for FontDescriptor
impl Data for FontDescriptor
source§impl Debug for FontDescriptor
impl Debug for FontDescriptor
source§impl Default for FontDescriptor
impl Default for FontDescriptor
source§impl From<FontDescriptor> for Value
impl From<FontDescriptor> for Value
source§fn from(val: FontDescriptor) -> Value
fn from(val: FontDescriptor) -> Value
Converts to this type from the input type.
source§impl PartialEq<FontDescriptor> for FontDescriptor
impl PartialEq<FontDescriptor> for FontDescriptor
source§fn eq(&self, other: &FontDescriptor) -> bool
fn eq(&self, other: &FontDescriptor) -> bool
This method tests for
self
and other
values to be equal, and is used
by ==
.source§impl ValueType for FontDescriptor
impl ValueType for FontDescriptor
source§fn try_from_value(value: &Value) -> Result<Self, ValueTypeError>
fn try_from_value(value: &Value) -> Result<Self, ValueTypeError>
Attempt to convert the generic
Value
into this type.impl StructuralPartialEq for FontDescriptor
Auto Trait Implementations§
impl RefUnwindSafe for FontDescriptor
impl Send for FontDescriptor
impl Sync for FontDescriptor
impl Unpin for FontDescriptor
impl UnwindSafe for FontDescriptor
Blanket Implementations§
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> RoundFrom<T> for T
impl<T> RoundFrom<T> for T
§fn round_from(x: T) -> T
fn round_from(x: T) -> T
Performs the conversion.
§impl<T, U> RoundInto<U> for Twhere
U: RoundFrom<T>,
impl<T, U> RoundInto<U> for Twhere U: RoundFrom<T>,
§fn round_into(self) -> U
fn round_into(self) -> U
Performs the conversion.