1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 13:20:05 -04:00

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

This commit is contained in:
Emil Ernerfeldt
2021-10-10 15:35:13 +02:00
parent 88d087b462
commit e547b149ca
15 changed files with 160 additions and 90 deletions

View File

@@ -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)*) => {

View File

@@ -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);
}
}
}
}

View File

@@ -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(

View File

@@ -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,

View File

@@ -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.