Commit Graph

18 Commits

Author SHA1 Message Date
Emil Ernerfeldt 49fad9a7b2 Roll out new egui icon and logo (#7995)
For the first time _ever_, egui has a logo!

<img width="3925" height="1406" alt="egui-logo"
src="https://github.com/user-attachments/assets/cfaf1d43-9338-490f-ae82-99b420baa1b0"
/>

Made by [Studio Gruhl](https://www.studiogruhl.com/) and paid for by
[Rerun.io](https://rerun.io/).
2026-03-21 22:47:15 +01:00
Lucas Meurer 8b2315375b TextEdit Atom prefix/suffix (#7587)
* part of https://github.com/emilk/egui/issues/7264
* part of https://github.com/emilk/egui/issues/7445

This PR changes the layout within the TextEdit to be done with
AtomLayout. It also adds a Prefix and Postfix that allows adding
permanent icons / icon buttons within the textedit.

Breaking changes:
- Removed `TextEdit::hint_text_font`. Hint text is an atom now, so the
font can be set that way

<img width="264" height="130" alt="Screenshot 2025-10-06 at 12 25 21"
src="https://github.com/user-attachments/assets/03b6b56b-ca82-4ac3-b5c0-585cca336834"
/>

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Co-authored-by: lucasmerlin <8009393+lucasmerlin@users.noreply.github.com>
2026-03-20 11:29:32 +01:00
Lucas Meurer 14afefa252 Fix galley width calculation being off due to subpixel binning (#7972)
- fix for https://github.com/rerun-io/reality/pull/1075

The galleys row size was calculated by looking at the last glyphs pos_x,
which got changed to be rounded to integers when we added subpixel
binning. This introduced a subtle bug which caused the width of galleys
to be slightly off.
This PR fixes this by looking at the actual cursor position instead,
which is not rounded.

Also added a test to ensure this is correct. Previously, for the second
and last line, the `x` was too close to the `0`.

<img width="48" height="67" alt="image"
src="https://github.com/user-attachments/assets/a69a4cc3-b3f3-4553-ab92-73cb2e7a358c"
/>

---------

Co-authored-by: lucasmerlin <8009393+lucasmerlin@users.noreply.github.com>
2026-03-12 13:49:16 +01:00
Emil Ernerfeldt 9e95b9ca50 Don't expand widgets on hover (#7808)
* Part of https://github.com/emilk/egui/issues/5605

This changes the default style of egui.

The problem with "expanding" widgets is that they now want to paint
outside their own bounds, which then requires all parent UIs to have
proper margins.

It also means hovered things are no longer properly aligned with every
other widget.
2025-12-22 22:30:53 +01:00
valadaptive 609dd2d28e Replace ab_glyph with Skrifa + vello_cpu; enable font hinting (#7694)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

* Closes N/A
* [x] I have followed the instructions in the PR template

I'll probably come back to this and clean it up a bit. This PR
reimplements ab_glyph's functionality on top of Skrifa, a somewhat
lower-level font API that's being used in Chrome now.

Skrifa doesn't perform rasterization itself, so I'm using
[vello_cpu](https://github.com/linebender/vello) from the Linebender
project for rasterization. It's still in its early days, but I believe
it's already quite fast. It also supports color and gradient fills, so
color emoji support will be easier.

Skrifa also supports font hinting, which should make text look a bit
nicer / less blurry.

Here's the current ab_glyph rendering:

<img width="1592" height="1068" alt="image"
src="https://github.com/user-attachments/assets/2385b66e-23f8-4c6e-b8c2-ea90e0eea4e4"
/>

Here's Skrifa *without* hinting--it looks almost identical, but there
are some subpixel differences, probably due to rasterizer behavior:

<img width="1592" height="1068" alt="image"
src="https://github.com/user-attachments/assets/a815f3e9-65ac-4940-bc00-571177bef53d"
/>

Here's Skrifa  *with* hinting:

<img width="1592" height="1068" alt="image"
src="https://github.com/user-attachments/assets/d6cc0669-3537-4377-bba9-ed5ef09664db"
/>

Hinting does make the horizontal strokes look a bit bolder, which makes
me wonder once again about increasing the font weight from "light" to
"regular".

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-12-06 16:11:33 +01:00
Emil Ernerfeldt f74b7c7e79 Paint mouse cursor in kittest snapshot images (#7721)
Very simple triangle shape, but helps understand why a widget has a
hovered effect
2025-11-18 06:24:03 +01:00
Emil Ernerfeldt 9a073d9399 Prevent widgets sometimes appearing to move relative to each other (#7710)
Sometimes when moving a window, having a tooltip attached to the mouse
pointer, or scrolling a `ScrollArea`, you would see this disturbing
effect:


![drift-bug](https://github.com/user-attachments/assets/013a5f49-ee02-417c-8441-1e1a0369e8bd)

This is caused by us rounding many visual elements (lines, rectangles,
text, …) to physical pixels in order to keep them sharp. If the
window/tooltip itself is not rounded to a physical pixel, then you can
get this behavior.

So from now on the position of all
areas/windows/tooltips/popups/ScrollArea gets rounded to the closes
pixel.

* Unlocked by https://github.com/emilk/egui/pull/7709
2025-11-13 10:52:46 +01:00
Emil Ernerfeldt 47a437403f Use software texture filtering in kittest (#7602) 2025-10-08 16:24:02 +02:00
Emil Ernerfeldt 72b9b9d750 Increase default text size from 12.5 to 13.0 (#7521) 2025-09-09 15:47:24 +02:00
valadaptive d5b0a6f446 More even text kerning (#7431)
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-09-08 17:29:41 +02:00
Emil Ernerfeldt f46926aaf1 Improve texture filtering by doing it in gamma space (#7311)
* Closes https://github.com/emilk/egui/pull/5839

This makes some transparent images look a lot nicer when blended:


![image](https://github.com/user-attachments/assets/7f370aaf-886a-423c-8391-c378849b63ca)

Cursive text will also look nicer.

This unfortunately changes the contract of what
`register_native_texture` expects

---------

Co-authored-by: Adrian Blumer <blumer.adrian@gmail.com>
2025-07-07 17:46:27 +02:00
Lucas Meurer 0152a87519 Create custom egui_kittest::Node (#7138)
This adds a custom Node struct with proper support for egui types
(`Key`, `Modifiers`, `egui::Event`, `Rect`) instead of needing to use
the kittest / accesskit types.

I also changed the `click` function to do a proper mouse move / mouse
down instead of the accesskit click. Also added `accesskit_click` to
trigger the accesskit event. This resulted in some changed snapshots,
since the elements are now hovered.

Also renamed `press_key` to `key_press` for consistency with
`key_down/key_up`.

Also removed the Deref to the AccessKit Node, to make it clearer when to
expect egui and when to expect accesskit types.

* Closes #5705 
* [x] I have followed the instructions in the PR template
2025-06-17 12:17:38 +02:00
Lucas Meurer 6eb7bb6e08 Add AtomLayout, abstracing layouting within widgets (#5830)
Today each widget does its own custom layout, which has some drawbacks:
- not very flexible
- you can add an `Image` to `Button` but it will always be shown on the
left side
  - you can't add a `Image` to a e.g. a `SelectableLabel`
- a lot of duplicated code

This PR introduces `Atoms` and `AtomLayout` which abstracts over "widget
content" and layout within widgets, so it'd be possible to add images /
text / custom rendering (for e.g. the checkbox) to any widget.

A simple custom button implementation is now as easy as this:
```rs
pub struct ALButton<'a> {
    al: AtomicLayout<'a>,
}

impl<'a> ALButton<'a> {
    pub fn new(content: impl IntoAtomics) -> Self {
        Self { al: content.into_atomics() }
    }
}

impl<'a> Widget for ALButton<'a> {
    fn ui(mut self, ui: &mut Ui) -> Response {
        let response = ui.ctx().read_response(ui.next_auto_id());

        let visuals = response.map_or(&ui.style().visuals.widgets.inactive, |response| {
            ui.style().interact(&response)
        });

        self.al.frame = self
            .al
            .frame
            .inner_margin(ui.style().spacing.button_padding)
            .fill(visuals.bg_fill)
            .stroke(visuals.bg_stroke)
            .corner_radius(visuals.corner_radius);

        self.al.show(ui)
    }
}

```

The initial implementation only does very basic layout, just enough to
be able to implement most current egui widgets, so:
- only horizontal layout
- everything is centered
- a single item may grow/shrink based on the available space
- everything can be contained in a Frame


There is a trait `IntoAtoms` that conveniently allows you to construct
`Atoms` from a tuple
```
   ui.button((Image::new("image.png"), "Click me!"))
```
to get a button with image and text.


This PR reimplements three egui widgets based on the new AtomLayout:
 - Button
   - matches the old button pixel-by-pixel
- Button with image is now [properly
aligned](https://github.com/emilk/egui/pull/5830/files#diff-962ce2c68ab50724b01c6b64c683c4067edd9b79fcdcb39a6071021e33ebe772)
in justified layouts
   - selected button style now matches SelecatbleLabel look
- For some reason the DragValue text seems shifted by a pixel almost
everywhere, but I think it's more centered now, yay?
 - Checkbox
- basically pixel-perfect but apparently the check mesh is very slightly
different so I had to update the snapshot
   - somehow needs a bit more space in some snapshot tests?
 - RadioButton
   - pixel-perfect
   - somehow needs a bit more space in some snapshot tests?

I plan on updating TextEdit based on AtomLayout in a separate PR (so
you could use it to add a icon within the textedit frame).
2025-06-13 09:39:52 +02:00
Emil Ernerfeldt 2058dcb881 Improve text sharpness (#5838)
This improves the sharpness of text slightly, thanks to
<https://hikogui.org/2022/10/24/the-trouble-with-anti-aliasing.html> by
@hikogui (🙏 ).

The difference is very small, but in dark mode (bright text on dark
background) text is sometimes significantly sharper, and also slightly
brighter.

The difference in light mode (dark text on light background) is much
smaller (barely perceptable).

To compare the before/after I suggest you open both in new tabs, then
quickly change between them.

### Low-DPI
#### Before
![Code Editor
old](https://github.com/user-attachments/assets/e10a3cad-932f-48cd-b7d6-5bfe70954c5e)

#### After
![Code
Editor](https://github.com/user-attachments/assets/2e7383fe-8023-4425-91c8-93df3c22c0fe)

#### Before

![old-white](https://github.com/user-attachments/assets/51c41c59-e897-4831-857a-f3ffe17ce7d4)

#### After

![new-white](https://github.com/user-attachments/assets/4ac6f951-8c57-4bcc-a5d5-788cf52ea7d8)

### High-DPI
The difference is starkest on low-DPI screens (like the above
screenshots). On high-DPI screens, the difference is much smaller

#### Before
![widget_gallery
old](https://github.com/user-attachments/assets/f2149a30-aef8-4383-b48c-73d33a03ca02)

#### After

![widget_gallery](https://github.com/user-attachments/assets/c9ceb8be-8a32-490c-9364-2c6562b741f6)
2025-03-21 12:56:47 +01:00
Emil Ernerfeldt 3f731ec794 Fix semi-transparent colors appearing too bright (#5824)
The bug was in `Color32::from_rgba_unmultiplied` and by extension
affects:

* `Color32::from_rgba_unmultiplied`
* `hex_color!`
* `HexColor`
* `ColorImage::from_rgba_unmultiplied`
* All images with transparency (png, webp, …)
* `Color32::from_white_alpha`

The bug caused translucent colors to appear too bright.

## More
Color is hard.

When I started out egui I thought "linear space is objectively better,
for everything!" and then I've been slowly walking that back for various
reasons:

* sRGB textures not available everywhere
* gamma-space is more _perceptually_ even, so it makes sense to use for
anti-aliasing
* other applications do everything in gamma space, so that's what people
expect (this PR)

Similarly, pre-multiplied alpha _makes sense_ for blending colors. It
also enables additive colors, which is nice. But it does complicate
things. Especially when mixed with sRGB/gamma (As @karhu [points
out](https://github.com/emilk/egui/pull/5824#issuecomment-2738099254)).

## Related
* Closes https://github.com/emilk/egui/issues/5751
* Closes https://github.com/emilk/egui/issues/5771 ? (probably; hard to
tell without a repro)
* But not https://github.com/emilk/egui/issues/5810

## TODO
* [x] I broke the RGBA u8 color picker. Fix it

---------

Co-authored-by: Andreas Reich <andreas@rerun.io>
2025-03-21 10:45:25 +01:00
Emil Ernerfeldt 3c07e01d08 Improve tessellation quality (#5669)
## Defining what `Rounding` is
This PR defines what `Rounding` means: it is the corner radius of
underlying `RectShape` rectangle. If you use `StrokeKind::Inside`, this
means the rounding is of the outer part of the stroke. Conversely, if
you use `StrokeKind::Outside`, the stroke is outside the rounded
rectangle, so the stroke has an inner radius or `rounding`, and an outer
radius that is larger by `stroke.width`.

This definitions is the same as Figma uses.

## Improving general shape rendering
The rendering of filled shapes (rectangles, circles, paths, bezier) has
been rewritten. Instead of first painting the fill with the stroke on
top, we now paint them as one single mesh with shared vertices at the
border. This has several benefits:

* Less work (faster and with fewer vertices produced)
* No overdraw (nicer rendering of translucent shapes)
* Correct blending of stroke and fill

The logic for rendering thin strokes has also been improved, so that the
width of a stroke of `StrokeKind::Outside` never affects the filled area
(this used to be wrong for thin strokes).

## Improving of rectangle rendering
Rectangles also has specific improvements in how thin rectangles are
painted.
The handling of "Blur width" is also a lot better, and now works for
rectangles with strokes.
There also used to be bugs with specific combinations of corner radius
and stroke width, that are now fixed.

##  But why?
With the new `egui::Scene` we end up with a lot of zoomed out shapes,
with sub-pixel strokes. These need to look good! One thing led to
another, and then I became obsessive 😅

## Tessellation Test
In order to investigate the rendering, I created a Tessellation Test in
the `egui_demo_lib`.

[Try it
here](https://egui-pr-preview.github.io/pr/5669-emilkimprove-tessellator)

![Screenshot 2025-02-04 at 08 45
50](https://github.com/user-attachments/assets/20b47a30-de6a-4ff5-885b-2e2fd6d88321)


![image](https://github.com/user-attachments/assets/e17c50eb-5ae7-48d4-bb0d-4f2165075897)
2025-02-04 11:30:12 +01:00
Emil Ernerfeldt 525d435a84 Require a StrokeKind when painting rectangles with strokes (#5648)
This is a breaking change, requiring users to think about wether the
stroke is inside/centered/outside the rect.

When in doubt, add `egui::StrokeKind::Inside` to the function call.
2025-01-29 15:52:49 +01:00
lucasmerlin 46b58e5bcc Add Harness::new_eframe and TestRenderer trait (#5539)
Co-authored-by: Andreas Reich <r_andreas2@web.de>
2025-01-02 17:48:39 +01:00