1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

Replace a special Color32::PLACEHOLDER with widget fallback color (#3727)

This introduces a special `Color32::PLACEHOLDER` which, during text
painting, will be replaced with `TextShape::fallback_color`.

The fallback color is mandatory to set in all text painting. Usually
this comes from the current visual style.

This lets users color only parts of a `WidgetText` (using e.g. a
`LayoutJob` or a `Galley`), where the uncolored parts (using
`Color32::PLACEHOLDER`) will be replaced by a default widget color (e.g.
blue for a hyperlink).

For instance, you can color the `⚠️`-emoji red in a piece of text red
and leave the rest of the text uncolored. The color of the rest of the
text will then depend on wether or not you put that text in a label, a
button, or a hyperlink.

Overall this simplifies a lot of complexity in the code but comes with a
few breaking changes:

* `TextShape::new`, `Shape::galley`, and `Painter::galley` now take a
fallback color by argument
* `Shape::galley_with_color` has been deprecated (use `Shape::galley`
instead)
* `Painter::galley_with_color` has been deprecated (use
`Painter::galley` instead)
* `WidgetTextGalley` is gone (use `Arc<Galley>` instead)
* `WidgetTextJob` is gone (use `LayoutJob` instead)
* `RichText::into_text_job` has been replaced with
`RichText::into_layout_job`
* `WidgetText::into_text_job` has been replaced with
`WidgetText::into_layout_job`
This commit is contained in:
Emil Ernerfeldt
2023-12-22 15:09:10 +01:00
committed by GitHub
parent e36b981118
commit 0561fcaba9
23 changed files with 270 additions and 309 deletions

View File

@@ -211,24 +211,36 @@ impl Shape {
) -> Self {
let galley = fonts.layout_no_wrap(text.to_string(), font_id, color);
let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size()));
Self::galley(rect.min, galley)
Self::galley(rect.min, galley, color)
}
/// Any uncolored parts of the [`Galley`] (using [`Color32::PLACEHOLDER`]) will be replaced with the given color.
///
/// Any non-placeholder color in the galley takes precedence over this fallback color.
#[inline]
pub fn galley(pos: Pos2, galley: Arc<Galley>, fallback_color: Color32) -> Self {
TextShape::new(pos, galley, fallback_color).into()
}
/// All text color in the [`Galley`] will be replaced with the given color.
#[inline]
pub fn galley_with_override_text_color(
pos: Pos2,
galley: Arc<Galley>,
text_color: Color32,
) -> Self {
TextShape::new(pos, galley, text_color)
.with_override_text_color(text_color)
.into()
}
#[inline]
pub fn galley(pos: Pos2, galley: Arc<Galley>) -> Self {
TextShape::new(pos, galley).into()
}
#[inline]
/// The text color in the [`Galley`] will be replaced with the given color.
#[deprecated = "Use `Shape::galley` or `Shape::galley_with_override_text_color` instead"]
pub fn galley_with_color(pos: Pos2, galley: Arc<Galley>, text_color: Color32) -> Self {
TextShape {
override_text_color: Some(text_color),
..TextShape::new(pos, galley)
}
.into()
Self::galley_with_override_text_color(pos, galley, text_color)
}
#[inline]
pub fn mesh(mesh: Mesh) -> Self {
crate::epaint_assert!(mesh.is_valid());
Self::Mesh(mesh)
@@ -669,9 +681,14 @@ pub struct TextShape {
/// You can also set an underline when creating the galley.
pub underline: Stroke,
/// Any [`Color32::PLACEHOLDER`] in the galley will be replaced by the given color.
/// Affects everything: backgrounds, glyphs, strikethough, underline, etc.
pub fallback_color: Color32,
/// If set, the text color in the galley will be ignored and replaced
/// with the given color.
/// This will NOT replace background color nor strikethrough/underline color.
///
/// This only affects the glyphs and will NOT replace background color nor strikethrough/underline color.
pub override_text_color: Option<Color32>,
/// Rotate text by this many radians clockwise.
@@ -680,12 +697,16 @@ pub struct TextShape {
}
impl TextShape {
/// The given fallback color will be used for any uncolored part of the galley (using [`Color32::PLACEHOLDER`]).
///
/// Any non-placeholder color in the galley takes precedence over this fallback color.
#[inline]
pub fn new(pos: Pos2, galley: Arc<Galley>) -> Self {
pub fn new(pos: Pos2, galley: Arc<Galley>, fallback_color: Color32) -> Self {
Self {
pos,
galley,
underline: Stroke::NONE,
fallback_color,
override_text_color: None,
angle: 0.0,
}
@@ -696,6 +717,27 @@ impl TextShape {
pub fn visual_bounding_rect(&self) -> Rect {
self.galley.mesh_bounds.translate(self.pos.to_vec2())
}
#[inline]
pub fn with_underline(mut self, underline: Stroke) -> Self {
self.underline = underline;
self
}
/// Use the given color for the text, regardless of what color is already in the galley.
#[inline]
pub fn with_override_text_color(mut self, override_text_color: Color32) -> Self {
self.override_text_color = Some(override_text_color);
self
}
/// Rotate text by this many radians clockwise.
/// The pivot is `pos` (the upper left corner of the text).
#[inline]
pub fn with_angle(mut self, angle: f32) -> Self {
self.angle = angle;
self
}
}
impl From<TextShape> for Shape {

View File

@@ -1473,6 +1473,7 @@ impl Tessellator {
galley,
underline,
override_text_color,
fallback_color,
angle,
} = text_shape;
@@ -1539,11 +1540,16 @@ impl Tessellator {
let Vertex { pos, uv, mut color } = *vertex;
if let Some(override_text_color) = override_text_color {
// Only override the glyph color (not background color, strike-through color, etc)
if row.visuals.glyph_vertex_range.contains(&i) {
color = *override_text_color;
}
} else if color == Color32::PLACEHOLDER {
color = *fallback_color;
}
crate::epaint_assert!(color != Color32::PLACEHOLDER, "A placeholder color made it to the tessellator. You forgot to set a fallback color.");
let offset = if *angle == 0.0 {
pos.to_vec2()
} else {

View File

@@ -531,12 +531,7 @@ impl Fonts {
font_id: FontId,
wrap_width: f32,
) -> Arc<Galley> {
self.layout_job(LayoutJob::simple(
text,
font_id,
crate::Color32::TEMPORARY_COLOR,
wrap_width,
))
self.layout(text, font_id, crate::Color32::PLACEHOLDER, wrap_width)
}
}

View File

@@ -509,8 +509,9 @@ pub struct RowVisuals {
/// Does NOT include leading or trailing whitespace glyphs!!
pub mesh_bounds: Rect,
/// The range of vertices in the mesh the contain glyphs.
/// Before comes backgrounds (if any), and after any underlines and strikethrough.
/// The range of vertices in the mesh that contain glyphs (as opposed to background, underlines, strikethorugh, etc).
///
/// The glyph vertices comes before backgrounds (if any), and after any underlines and strikethrough.
pub glyph_vertex_range: Range<usize>,
}