Browse Source

Improve docs, especially of epaint, and add epaint/CHANGELOG.md

pull/790/head
Emil Ernerfeldt 3 years ago
parent
commit
e547b149ca
  1. 4
      CHANGELOG.md
  2. 6
      egui/src/context.rs
  3. 4
      egui/src/lib.rs
  4. 2
      egui/src/response.rs
  5. 12
      egui/src/widgets/mod.rs
  6. 2
      emath/Cargo.toml
  7. 4
      emath/src/lib.rs
  8. 9
      epaint/CHANGELOG.md
  9. 2
      epaint/Cargo.toml
  10. 17
      epaint/src/lib.rs
  11. 102
      epaint/src/shape.rs
  12. 43
      epaint/src/tessellator.rs
  13. 4
      epaint/src/text/fonts.rs
  14. 32
      epaint/src/text/text_layout_types.rs
  15. 7
      epi/src/lib.rs

4
CHANGELOG.md

@ -2,7 +2,7 @@
All notable changes to the egui crate will be documented in this file.
NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`egui-winit`](egui-winit/CHANGELOG.md) and [`egui_glium`](egui_glium/CHANGELOG.md) have their own changelogs!
NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`egui-winit`](egui-winit/CHANGELOG.md) and [`egui_glium`](egui_glium/CHANGELOG.md) have their own changelogs!
## Unreleased
@ -10,7 +10,7 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`eg
### Added ⭐
* Add horizontal scrolling support to `ScrollArea` and `Window` (opt-in).
* `TextEdit::layouter`: Add custom text layout for e.g. syntax highlighting or WYSIWYG.
* `Fonts::layout_job*`: New text layout engine allowing mixing fonts, colors and styles, with underlining and strikethrough.
* `Fonts::layout_job`: New text layout engine allowing mixing fonts, colors and styles, with underlining and strikethrough.
* Add feature `"serialize"` separatedly from `"persistence"`.
* Add `egui::widgets::global_dark_light_mode_buttons` to easily add buttons for switching the egui theme.
* `TextEdit` can now be used to show text which can be selectedd and copied, but not edited.

6
egui/src/context.rs

@ -624,10 +624,14 @@ impl Context {
/// Tessellate the given shapes into triangle meshes.
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedMesh> {
// A tempting optimization is to reuse the tessellation from last frame if the
// shapes are the same, but just comparing the shapes takes about 50% of the time
// it takes to tessellate them, so it is not a worth optimization.
let mut tessellation_options = self.memory().options.tessellation_options;
tessellation_options.pixels_per_point = self.pixels_per_point();
tessellation_options.aa_size = 1.0 / self.pixels_per_point();
let paint_stats = PaintStats::from_shapes(&shapes); // TODO: internal allocations
let paint_stats = PaintStats::from_shapes(&shapes);
let clipped_meshes = tessellator::tessellate_shapes(
shapes,
tessellation_options,

4
egui/src/lib.rs

@ -472,8 +472,8 @@ macro_rules! trace {
// ----------------------------------------------------------------------------
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
/// or with the `debug_egui_assert` feature in debug builds.
/// An assert that is only active when `egui` is compiled with the `extra_asserts` feature
/// or with the `extra_debug_asserts` feature in debug builds.
#[macro_export]
macro_rules! egui_assert {
($($arg: tt)*) => {

2
egui/src/response.rs

@ -408,7 +408,7 @@ impl Response {
/// Check for more interactions (e.g. sense clicks on a `Response` returned from a label).
///
/// Note that this call will not add any hover-effects to the widget, so when possible
/// it is better to give the widget a `Sense` instead, e.g. using `[Label::sense]`.
/// it is better to give the widget a `Sense` instead, e.g. using [`crate::Label::sense`].
///
/// ```
/// # let mut ui = egui::Ui::__test();

12
egui/src/widgets/mod.rs

@ -19,18 +19,22 @@ mod separator;
mod slider;
pub(crate) mod text_edit;
pub use button::*;
pub use drag_value::DragValue;
pub use hyperlink::*;
pub use image::Image;
pub use label::*;
pub use progress_bar::ProgressBar;
pub use selected_label::*;
pub use separator::*;
pub use {button::*, drag_value::DragValue, image::Image, slider::*, text_edit::*};
pub use selected_label::SelectableLabel;
pub use separator::Separator;
pub use slider::*;
pub use text_edit::*;
// ----------------------------------------------------------------------------
/// Anything implementing Widget can be added to a [`Ui`] with [`Ui::add`].
///
/// `[Button]`, `[Label]`, [`Slider`], etc all implement the `Widget` trait.
/// [`Button`], [`Label`], [`Slider`], etc all implement the `Widget` trait.
///
/// Note that the widgets (`Button`, `TextEdit` etc) are
/// [builders](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html),

2
emath/Cargo.toml

@ -24,9 +24,9 @@ all-features = true
[dependencies]
# Add compatability with https://github.com/kvark/mint
bytemuck = { version = "1.7.2", features = ["derive"], optional = true }
mint = { version = "0.5.6", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
bytemuck = { version = "1.7.2", features = ["derive"], optional = true }
[features]
default = []

4
emath/src/lib.rs

@ -358,8 +358,8 @@ fn test_normalized_angle() {
// ----------------------------------------------------------------------------
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
/// or with the `debug_egui_assert` feature in debug builds.
/// An assert that is only active when `emath` is compiled with the `extra_asserts` feature
/// or with the `extra_debug_asserts` feature in debug builds.
#[macro_export]
macro_rules! emath_assert {
($($arg: tt)*) => {

9
epaint/CHANGELOG.md

@ -0,0 +1,9 @@
# epaint changelog
All notable changes to the epaint crate will be documented in this file.
## Unreleased
* `Fonts::layout_job`: New text layout engine allowing mixing fonts, colors and styles, with underlining and strikethrough.
* New `CircleShape`, `PathShape`, `RectShape` and `TextShape` used in `enum Shape`.
* Add support for rotated text (see `TextShape`).
* Added `"convert_bytemuck"` feature.

2
epaint/Cargo.toml

@ -30,11 +30,11 @@ emath = { version = "0.14.0", path = "../emath" }
ab_glyph = "0.2.11"
ahash = { version = "0.7", features = ["std"], default-features = false }
atomic_refcell = { version = "0.1", optional = true } # Used instead of parking_lot when you are always using epaint in a single thread. About as fast as parking_lot. Panics on multi-threaded use.
bytemuck = { version = "1.7.2", features = ["derive"], optional = true }
cint = { version = "^0.2.2", optional = true }
nohash-hasher = "0.2"
parking_lot = { version = "0.11", optional = true } # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios.
serde = { version = "1", features = ["derive"], optional = true }
bytemuck = { version = "1.7.2", features = ["derive"], optional = true }
[features]
default = ["default_fonts", "multi_threaded"]

17
epaint/src/lib.rs

@ -1,4 +1,9 @@
//! 2D graphics/rendering. Fonts, textures, color, geometry, tessellation etc.
//! A simple 2D graphics library for turning simple 2D shapes and text into textured triangles.
//!
//! Made for [`egui`](https://github.com/emilk/egui/).
//!
//! Create some [`Shape`]:s and pass them to [`tessellate_shapes`] to generate [`Mesh`]:es
//! that you can then paint using some graphics API of your choice (e.g. OpenGL).
// Forbid warnings in release builds:
#![cfg_attr(not(debug_assertions), deny(warnings))]
@ -91,8 +96,8 @@ pub use {
shape::{CircleShape, PathShape, RectShape, Shape, TextShape},
stats::PaintStats,
stroke::Stroke,
tessellator::{TessellationOptions, Tessellator},
text::{Galley, TextStyle},
tessellator::{tessellate_shapes, TessellationOptions, Tessellator},
text::{Fonts, Galley, TextStyle},
texture_atlas::{Texture, TextureAtlas},
};
@ -129,7 +134,7 @@ impl Default for TextureId {
/// A [`Shape`] within a clip rectangle.
///
/// Everything is using logical points.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct ClippedShape(
/// Clip / scissor rectangle.
/// Only show the part of the [`Shape`] that falls within this.
@ -153,8 +158,8 @@ pub struct ClippedMesh(
// ----------------------------------------------------------------------------
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
/// or with the `debug_egui_assert` feature in debug builds.
/// An assert that is only active when `epaint` is compiled with the `extra_asserts` feature
/// or with the `extra_debug_asserts` feature in debug builds.
#[macro_export]
macro_rules! epaint_assert {
($($arg: tt)*) => {

102
epaint/src/shape.rs

@ -123,6 +123,57 @@ impl Shape {
pub fn galley(pos: Pos2, galley: std::sync::Arc<Galley>) -> Self {
TextShape::new(pos, galley).into()
}
pub fn mesh(mesh: Mesh) -> Self {
crate::epaint_assert!(mesh.is_valid());
Self::Mesh(mesh)
}
}
/// ## Inspection and transforms
impl Shape {
#[inline(always)]
pub fn texture_id(&self) -> super::TextureId {
if let Shape::Mesh(mesh) = self {
mesh.texture_id
} else {
super::TextureId::Egui
}
}
/// Move the shape by this many points, in-place.
pub fn translate(&mut self, delta: Vec2) {
match self {
Shape::Noop => {}
Shape::Vec(shapes) => {
for shape in shapes {
shape.translate(delta);
}
}
Shape::Circle(circle_shape) => {
circle_shape.center += delta;
}
Shape::LineSegment { points, .. } => {
for p in points {
*p += delta;
}
}
Shape::Path(path_shape) => {
for p in &mut path_shape.points {
*p += delta;
}
}
Shape::Rect(rect_shape) => {
rect_shape.rect = rect_shape.rect.translate(delta);
}
Shape::Text(text_shape) => {
text_shape.pos += delta;
}
Shape::Mesh(mesh) => {
mesh.translate(delta);
}
}
}
}
// ----------------------------------------------------------------------------
@ -398,54 +449,3 @@ fn dashes_from_line(
position_on_segment -= segment_length;
});
}
/// ## Operations
impl Shape {
pub fn mesh(mesh: Mesh) -> Self {
crate::epaint_assert!(mesh.is_valid());
Self::Mesh(mesh)
}
#[inline(always)]
pub fn texture_id(&self) -> super::TextureId {
if let Shape::Mesh(mesh) = self {
mesh.texture_id
} else {
super::TextureId::Egui
}
}
/// Translate location by this much, in-place
pub fn translate(&mut self, delta: Vec2) {
match self {
Shape::Noop => {}
Shape::Vec(shapes) => {
for shape in shapes {
shape.translate(delta);
}
}
Shape::Circle(circle_shape) => {
circle_shape.center += delta;
}
Shape::LineSegment { points, .. } => {
for p in points {
*p += delta;
}
}
Shape::Path(path_shape) => {
for p in &mut path_shape.points {
*p += delta;
}
}
Shape::Rect(rect_shape) => {
rect_shape.rect = rect_shape.rect.translate(delta);
}
Shape::Text(text_shape) => {
text_shape.pos += delta;
}
Shape::Mesh(mesh) => {
mesh.translate(delta);
}
}
}
}

43
epaint/src/tessellator.rs

@ -257,21 +257,30 @@ pub enum PathType {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct TessellationOptions {
/// Size of a point in pixels, e.g. 2.0. Used to snap text to pixel boundaries.
/// Size of a point in pixels (DPI scaling), e.g. 2.0. Used to snap text to pixel boundaries.
pub pixels_per_point: f32,
/// Size of a pixel in points, e.g. 0.5, or larger if you want more blurry edges.
/// The size of a pixel (in points), used for anti-aliasing (smoothing of edges).
/// This is normally the inverse of [`Self::pixels_per_point`],
/// but you can make it larger if you want more blurry edges.
pub aa_size: f32,
/// Anti-aliasing makes shapes appear smoother, but requires more triangles and is therefore slower.
/// This setting does not affect text.
/// Default: `true`.
pub anti_alias: bool,
/// If `true` (default) cull certain primitives before tessellating them
/// If `true` (default) cull certain primitives before tessellating them.
/// This likely makes
pub coarse_tessellation_culling: bool,
/// Output the clip rectangles to be painted?
/// Output the clip rectangles to be painted.
pub debug_paint_clip_rects: bool,
/// Output the text-containing rectangles
/// Output the text-containing rectangles.
pub debug_paint_text_rects: bool,
/// If true, no clipping will be done
/// If true, no clipping will be done.
pub debug_ignore_clip_rects: bool,
}
@ -503,7 +512,11 @@ fn mul_color(color: Color32, factor: f32) -> Color32 {
// ----------------------------------------------------------------------------
/// Converts [`Shape`]s into [`Mesh`].
/// Converts [`Shape`]s into triangles ([`Mesh`]).
///
/// For performance reasons it is smart to reuse the same `Tessellator`.
///
/// Se also [`tessellate_shapes`], a convenient wrapper around [`Tessellator`].
pub struct Tessellator {
options: TessellationOptions,
/// Only used for culling
@ -513,6 +526,7 @@ pub struct Tessellator {
}
impl Tessellator {
/// Create a new [`Tessellator`].
pub fn from_options(options: TessellationOptions) -> Self {
Self {
options,
@ -524,12 +538,9 @@ impl Tessellator {
/// Tessellate a single [`Shape`] into a [`Mesh`].
///
/// * `shape`: the shape to tessellate
/// * `options`: tessellation quality
/// * `tex_size`: size of the font texture (required to normalize glyph uv rectangles)
/// * `out`: where the triangles are put
/// * `scratchpad_path`: if you plan to run `tessellate_shape`
/// many times, pass it a reference to the same `Path` to avoid excessive allocations.
/// * `tex_size`: size of the font texture (required to normalize glyph uv rectangles).
/// * `shape`: the shape to tessellate.
/// * `out`: triangles are appended to this.
pub fn tessellate_shape(&mut self, tex_size: [usize; 2], shape: Shape, out: &mut Mesh) {
let clip_rect = self.clip_rect;
let options = &self.options;
@ -776,13 +787,15 @@ impl Tessellator {
/// Turns [`Shape`]:s into sets of triangles.
///
/// The given shapes will be painted back-to-front (painters algorithm).
/// The given shapes will tessellated in the same order as they are given.
/// They will be batched together by clip rectangle.
///
/// * `shapes`: the shape to tessellate
/// * `shapes`: what to tessellate
/// * `options`: tessellation quality
/// * `tex_size`: size of the font texture (required to normalize glyph uv rectangles)
///
/// The implementation uses a [`Tessellator`].
///
/// ## Returns
/// A list of clip rectangles with matching [`Mesh`].
pub fn tessellate_shapes(

4
epaint/src/text/fonts.rs

@ -201,6 +201,8 @@ impl Default for FontDefinitions {
}
/// The collection of fonts used by `epaint`.
///
/// Required in order to paint text.
pub struct Fonts {
pixels_per_point: f32,
definitions: FontDefinitions,
@ -214,6 +216,8 @@ pub struct Fonts {
}
impl Fonts {
/// Create a new [`Fonts`] for text layout.
/// This call is expensive, so only create on [`Fonts`] and then reuse it.
pub fn new(pixels_per_point: f32, definitions: FontDefinitions) -> Self {
assert!(
0.0 < pixels_per_point && pixels_per_point < 100.0,

32
epaint/src/text/text_layout_types.rs

@ -11,12 +11,37 @@ use emath::*;
///
/// This supports mixing different fonts, color and formats (underline etc).
///
/// Pass this to [`Fonts::layout_job]` or [`crate::text::layout`].
/// Pass this to [`crate::Fonts::layout_job`] or [`crate::text::layout`].
///
/// ## Example:
/// ```
/// use epaint::{Color32, text::{LayoutJob, TextFormat}, TextStyle};
///
/// let mut job = LayoutJob::default();
/// job.append(
/// "Hello ",
/// 0.0,
/// TextFormat {
/// style: TextStyle::Body,
/// color: Color32::WHITE,
/// ..Default::default()
/// },
/// );
/// job.append(
/// "World!",
/// 0.0,
/// TextFormat {
/// style: TextStyle::Monospace,
/// color: Color32::BLACK,
/// ..Default::default()
/// },
/// );
/// ```
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct LayoutJob {
/// The complete text of this job, referenced by `LayoutSection`.
pub text: String, // TODO: Cow<'static, str>
pub text: String,
/// The different section, which can have different fonts, colors, etc.
pub sections: Vec<LayoutSection>,
@ -206,6 +231,9 @@ impl TextFormat {
// ----------------------------------------------------------------------------
/// Text that has been layed out, ready for painting.
///
/// You can create a [`Galley`] using [`crate::Fonts::layout_job`];
#[derive(Clone, Debug, PartialEq)]
pub struct Galley {
/// The job that this galley is the result of.

7
epi/src/lib.rs

@ -91,8 +91,8 @@ pub trait App {
/// Called once before the first frame.
///
/// Allows you to do setup code, e.g to call `[egui::Context::set_fonts]`,
/// `[egui::Context::set_visuals]` etc.
/// Allows you to do setup code, e.g to call [`egui::Context::set_fonts`],
/// [`egui::Context::set_visuals`] etc.
///
/// Also allows you to restore state, if there is a storage (required the "persistence" feature).
fn setup(
@ -106,6 +106,9 @@ pub trait App {
/// If `true` a warm-up call to [`Self::update`] will be issued where
/// `ctx.memory().everything_is_visible()` will be set to `true`.
///
/// This will help pre-caching all text, preventing stutter when
/// opening a window containing new glyphs.
///
/// In this warm-up call, all painted shapes will be ignored.
fn warm_up_enabled(&self) -> bool {
false

Loading…
Cancel
Save