refactor: no need to pass Fonts structure to tessellator
This makes the tesselator take only data as argument, which is a lot nicer.
This commit is contained in:
parent
0802a9d9c0
commit
8c4bb0d1d9
5 changed files with 37 additions and 19 deletions
|
@ -602,10 +602,14 @@ impl Context {
|
||||||
/// Tessellate the given shapes into triangle meshes.
|
/// Tessellate the given shapes into triangle meshes.
|
||||||
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedMesh> {
|
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedMesh> {
|
||||||
let mut tessellation_options = self.memory().options.tessellation_options;
|
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();
|
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); // TODO: internal allocations
|
||||||
let clipped_meshes =
|
let clipped_meshes = tessellator::tessellate_shapes(
|
||||||
tessellator::tessellate_shapes(shapes, tessellation_options, self.fonts());
|
shapes,
|
||||||
|
tessellation_options,
|
||||||
|
self.fonts().texture().size(),
|
||||||
|
);
|
||||||
*self.paint_stats.lock() = paint_stats.with_clipped_meshes(&clipped_meshes);
|
*self.paint_stats.lock() = paint_stats.with_clipped_meshes(&clipped_meshes);
|
||||||
clipped_meshes
|
clipped_meshes
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ impl Widget for &mut epaint::TessellationOptions {
|
||||||
fn ui(self, ui: &mut Ui) -> Response {
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
let epaint::TessellationOptions {
|
let epaint::TessellationOptions {
|
||||||
|
pixels_per_point: _,
|
||||||
aa_size: _,
|
aa_size: _,
|
||||||
anti_alias,
|
anti_alias,
|
||||||
coarse_tessellation_culling,
|
coarse_tessellation_culling,
|
||||||
|
|
|
@ -89,7 +89,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let fake_italics = false;
|
let fake_italics = false;
|
||||||
tessellator.tessellate_text(
|
tessellator.tessellate_text(
|
||||||
&fonts,
|
fonts.texture().size(),
|
||||||
egui::Pos2::ZERO,
|
egui::Pos2::ZERO,
|
||||||
&galley,
|
&galley,
|
||||||
egui::Color32::WHITE,
|
egui::Color32::WHITE,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#![allow(clippy::identity_op)]
|
#![allow(clippy::identity_op)]
|
||||||
|
|
||||||
use crate::{text::Fonts, *};
|
use crate::*;
|
||||||
use emath::*;
|
use emath::*;
|
||||||
use std::f32::consts::TAU;
|
use std::f32::consts::TAU;
|
||||||
|
|
||||||
|
@ -229,7 +229,9 @@ use self::PathType::{Closed, Open};
|
||||||
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "persistence", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct TessellationOptions {
|
pub struct TessellationOptions {
|
||||||
/// Size of a pixel in points, e.g. 0.5
|
/// Size of a point in pixels, 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.
|
||||||
pub aa_size: f32,
|
pub aa_size: f32,
|
||||||
/// Anti-aliasing makes shapes appear smoother, but requires more triangles and is therefore slower.
|
/// Anti-aliasing makes shapes appear smoother, but requires more triangles and is therefore slower.
|
||||||
/// By default this is enabled in release builds and disabled in debug builds.
|
/// By default this is enabled in release builds and disabled in debug builds.
|
||||||
|
@ -247,6 +249,7 @@ pub struct TessellationOptions {
|
||||||
impl Default for TessellationOptions {
|
impl Default for TessellationOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
pixels_per_point: 1.0,
|
||||||
aa_size: 1.0,
|
aa_size: 1.0,
|
||||||
anti_alias: true,
|
anti_alias: true,
|
||||||
coarse_tessellation_culling: true,
|
coarse_tessellation_culling: true,
|
||||||
|
@ -257,6 +260,13 @@ impl Default for TessellationOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TessellationOptions {
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn round_to_pixel(&self, point: f32) -> f32 {
|
||||||
|
(point * self.pixels_per_point).round() / self.pixels_per_point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Tessellate the given convex area into a polygon.
|
/// Tessellate the given convex area into a polygon.
|
||||||
fn fill_closed_path(
|
fn fill_closed_path(
|
||||||
path: &[PathPoint],
|
path: &[PathPoint],
|
||||||
|
@ -473,11 +483,11 @@ impl Tessellator {
|
||||||
///
|
///
|
||||||
/// * `shape`: the shape to tessellate
|
/// * `shape`: the shape to tessellate
|
||||||
/// * `options`: tessellation quality
|
/// * `options`: tessellation quality
|
||||||
/// * `fonts`: font source when tessellating text
|
/// * `tex_size`: size of the font texture (required to normalize glyph uv rectangles)
|
||||||
/// * `out`: where the triangles are put
|
/// * `out`: where the triangles are put
|
||||||
/// * `scratchpad_path`: if you plan to run `tessellate_shape`
|
/// * `scratchpad_path`: if you plan to run `tessellate_shape`
|
||||||
/// many times, pass it a reference to the same `Path` to avoid excessive allocations.
|
/// many times, pass it a reference to the same `Path` to avoid excessive allocations.
|
||||||
pub fn tessellate_shape(&mut self, fonts: &Fonts, shape: Shape, out: &mut Mesh) {
|
pub fn tessellate_shape(&mut self, tex_size: [usize; 2], shape: Shape, out: &mut Mesh) {
|
||||||
let clip_rect = self.clip_rect;
|
let clip_rect = self.clip_rect;
|
||||||
let options = self.options;
|
let options = self.options;
|
||||||
|
|
||||||
|
@ -485,7 +495,7 @@ impl Tessellator {
|
||||||
Shape::Noop => {}
|
Shape::Noop => {}
|
||||||
Shape::Vec(vec) => {
|
Shape::Vec(vec) => {
|
||||||
for shape in vec {
|
for shape in vec {
|
||||||
self.tessellate_shape(fonts, shape, out)
|
self.tessellate_shape(tex_size, shape, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Shape::Circle {
|
Shape::Circle {
|
||||||
|
@ -580,7 +590,7 @@ impl Tessellator {
|
||||||
out,
|
out,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.tessellate_text(fonts, pos, &galley, color, fake_italics, out);
|
self.tessellate_text(tex_size, pos, &galley, color, fake_italics, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -615,10 +625,9 @@ impl Tessellator {
|
||||||
stroke_path(&path.0, Closed, stroke, self.options, out);
|
stroke_path(&path.0, Closed, stroke, self.options, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn tessellate_text(
|
pub fn tessellate_text(
|
||||||
&mut self,
|
&mut self,
|
||||||
fonts: &Fonts,
|
tex_size: [usize; 2],
|
||||||
pos: Pos2,
|
pos: Pos2,
|
||||||
galley: &super::Galley,
|
galley: &super::Galley,
|
||||||
color: Color32,
|
color: Color32,
|
||||||
|
@ -634,8 +643,8 @@ impl Tessellator {
|
||||||
out.reserve_triangles(num_chars * 2);
|
out.reserve_triangles(num_chars * 2);
|
||||||
out.reserve_vertices(num_chars * 4);
|
out.reserve_vertices(num_chars * 4);
|
||||||
|
|
||||||
let inv_tex_w = 1.0 / fonts.texture().width as f32;
|
let inv_tex_w = 1.0 / tex_size[0] as f32;
|
||||||
let inv_tex_h = 1.0 / fonts.texture().height as f32;
|
let inv_tex_h = 1.0 / tex_size[1] as f32;
|
||||||
|
|
||||||
let clip_rect = self.clip_rect.expand(2.0); // Some fudge to handle letters that are slightly larger than expected.
|
let clip_rect = self.clip_rect.expand(2.0); // Some fudge to handle letters that are slightly larger than expected.
|
||||||
|
|
||||||
|
@ -653,8 +662,8 @@ impl Tessellator {
|
||||||
for (x_offset, uv_rect) in row.x_offsets.iter().zip(&row.uv_rects) {
|
for (x_offset, uv_rect) in row.x_offsets.iter().zip(&row.uv_rects) {
|
||||||
if let Some(glyph) = uv_rect {
|
if let Some(glyph) = uv_rect {
|
||||||
let mut left_top = pos + glyph.offset + vec2(*x_offset, row.y_min);
|
let mut left_top = pos + glyph.offset + vec2(*x_offset, row.y_min);
|
||||||
left_top.x = fonts.round_to_pixel(left_top.x); // Pixel-perfection.
|
left_top.x = self.options.round_to_pixel(left_top.x); // Pixel-perfection.
|
||||||
left_top.y = fonts.round_to_pixel(left_top.y); // Pixel-perfection.
|
left_top.y = self.options.round_to_pixel(left_top.y); // Pixel-perfection.
|
||||||
|
|
||||||
let rect = Rect::from_min_max(left_top, left_top + glyph.size);
|
let rect = Rect::from_min_max(left_top, left_top + glyph.size);
|
||||||
let uv = Rect::from_min_max(
|
let uv = Rect::from_min_max(
|
||||||
|
@ -711,14 +720,14 @@ impl Tessellator {
|
||||||
///
|
///
|
||||||
/// * `shapes`: the shape to tessellate
|
/// * `shapes`: the shape to tessellate
|
||||||
/// * `options`: tessellation quality
|
/// * `options`: tessellation quality
|
||||||
/// * `fonts`: font source when tessellating text
|
/// * `tex_size`: size of the font texture (required to normalize glyph uv rectangles)
|
||||||
///
|
///
|
||||||
/// ## Returns
|
/// ## Returns
|
||||||
/// A list of clip rectangles with matching [`Mesh`].
|
/// A list of clip rectangles with matching [`Mesh`].
|
||||||
pub fn tessellate_shapes(
|
pub fn tessellate_shapes(
|
||||||
shapes: Vec<ClippedShape>,
|
shapes: Vec<ClippedShape>,
|
||||||
options: TessellationOptions,
|
options: TessellationOptions,
|
||||||
fonts: &Fonts,
|
tex_size: [usize; 2],
|
||||||
) -> Vec<ClippedMesh> {
|
) -> Vec<ClippedMesh> {
|
||||||
let mut tessellator = Tessellator::from_options(options);
|
let mut tessellator = Tessellator::from_options(options);
|
||||||
|
|
||||||
|
@ -736,14 +745,14 @@ pub fn tessellate_shapes(
|
||||||
|
|
||||||
let out = &mut clipped_meshes.last_mut().unwrap().1;
|
let out = &mut clipped_meshes.last_mut().unwrap().1;
|
||||||
tessellator.clip_rect = clip_rect;
|
tessellator.clip_rect = clip_rect;
|
||||||
tessellator.tessellate_shape(fonts, shape, out);
|
tessellator.tessellate_shape(tex_size, shape, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.debug_paint_clip_rects {
|
if options.debug_paint_clip_rects {
|
||||||
for ClippedMesh(clip_rect, mesh) in &mut clipped_meshes {
|
for ClippedMesh(clip_rect, mesh) in &mut clipped_meshes {
|
||||||
tessellator.clip_rect = Rect::EVERYTHING;
|
tessellator.clip_rect = Rect::EVERYTHING;
|
||||||
tessellator.tessellate_shape(
|
tessellator.tessellate_shape(
|
||||||
fonts,
|
tex_size,
|
||||||
Shape::Rect {
|
Shape::Rect {
|
||||||
rect: *clip_rect,
|
rect: *clip_rect,
|
||||||
corner_radius: 0.0,
|
corner_radius: 0.0,
|
||||||
|
|
|
@ -12,6 +12,10 @@ pub struct Texture {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texture {
|
impl Texture {
|
||||||
|
pub fn size(&self) -> [usize; 2] {
|
||||||
|
[self.width, self.height]
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the textures as `sRGBA` premultiplied pixels, row by row, top to bottom.
|
/// Returns the textures as `sRGBA` premultiplied pixels, row by row, top to bottom.
|
||||||
pub fn srgba_pixels(&'_ self) -> impl Iterator<Item = super::Color32> + '_ {
|
pub fn srgba_pixels(&'_ self) -> impl Iterator<Item = super::Color32> + '_ {
|
||||||
use super::Color32;
|
use super::Color32;
|
||||||
|
|
Loading…
Reference in a new issue