Skip to content

Commit 692e23c

Browse files
committed
Cleanup before release
1 parent 2daf883 commit 692e23c

File tree

8 files changed

+93
-81
lines changed

8 files changed

+93
-81
lines changed

examples/custom-glyphs.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use glyphon::{
2-
Attrs, Buffer, Cache, Color, ContentType, CustomGlyph, RasterizationRequest, RasterizedCustomGlyph,
3-
Family, FontSystem, Metrics, Resolution, Shaping, SwashCache, TextArea, TextAtlas, TextBounds,
4-
TextRenderer, Viewport,
2+
Attrs, Buffer, Cache, Color, ContentType, CustomGlyph, Family, FontSystem, Metrics,
3+
RasterizeCustomGlyphRequest, RasterizedCustomGlyph, Resolution, Shaping, SwashCache, TextArea,
4+
TextAtlas, TextBounds, TextRenderer, Viewport,
55
};
66
use std::sync::Arc;
77
use wgpu::{
@@ -28,16 +28,13 @@ struct WindowState {
2828
queue: wgpu::Queue,
2929
surface: wgpu::Surface<'static>,
3030
surface_config: SurfaceConfiguration,
31-
3231
font_system: FontSystem,
3332
swash_cache: SwashCache,
3433
viewport: glyphon::Viewport,
3534
atlas: glyphon::TextAtlas,
3635
text_renderer: glyphon::TextRenderer,
3736
text_buffer: glyphon::Buffer,
38-
39-
rasterize_svg: Box<dyn Fn(RasterizationRequest) -> Option<RasterizedCustomGlyph>>,
40-
37+
rasterize_svg: Box<dyn Fn(RasterizeCustomGlyphRequest) -> Option<RasterizedCustomGlyph>>,
4138
// Make sure that the winit window is last in the struct so that
4239
// it is dropped after the wgpu surface is dropped, otherwise the
4340
// program may crash when closed. This is probably a bug in wgpu.
@@ -106,46 +103,47 @@ impl WindowState {
106103
let svg_0 = resvg::usvg::Tree::from_data(LION_SVG, &Default::default()).unwrap();
107104
let svg_1 = resvg::usvg::Tree::from_data(EAGLE_SVG, &Default::default()).unwrap();
108105

109-
let rasterize_svg = move |input: RasterizationRequest| -> Option<RasterizedCustomGlyph> {
110-
// Select the svg data based on the custom glyph ID.
111-
let (svg, content_type) = match input.id {
112-
0 => (&svg_0, ContentType::Mask),
113-
1 => (&svg_1, ContentType::Color),
114-
_ => return None,
115-
};
116-
117-
// Calculate the scale based on the "glyph size".
118-
let svg_size = svg.size();
119-
let scale_x = input.width as f32 / svg_size.width();
120-
let scale_y = input.height as f32 / svg_size.height();
121-
122-
let Some(mut pixmap) =
123-
resvg::tiny_skia::Pixmap::new(input.width as u32, input.height as u32)
124-
else {
125-
return None;
126-
};
127-
128-
let mut transform = resvg::usvg::Transform::from_scale(scale_x, scale_y);
106+
let rasterize_svg =
107+
move |input: RasterizeCustomGlyphRequest| -> Option<RasterizedCustomGlyph> {
108+
// Select the svg data based on the custom glyph ID.
109+
let (svg, content_type) = match input.id {
110+
0 => (&svg_0, ContentType::Mask),
111+
1 => (&svg_1, ContentType::Color),
112+
_ => return None,
113+
};
114+
115+
// Calculate the scale based on the "glyph size".
116+
let svg_size = svg.size();
117+
let scale_x = input.width as f32 / svg_size.width();
118+
let scale_y = input.height as f32 / svg_size.height();
119+
120+
let Some(mut pixmap) =
121+
resvg::tiny_skia::Pixmap::new(input.width as u32, input.height as u32)
122+
else {
123+
return None;
124+
};
125+
126+
let mut transform = resvg::usvg::Transform::from_scale(scale_x, scale_y);
127+
128+
// Offset the glyph by the subpixel amount.
129+
let offset_x = input.x_bin.as_float();
130+
let offset_y = input.y_bin.as_float();
131+
if offset_x != 0.0 || offset_y != 0.0 {
132+
transform = transform.post_translate(offset_x, offset_y);
133+
}
129134

130-
// Offset the glyph by the subpixel amount.
131-
let offset_x = input.x_bin.as_float();
132-
let offset_y = input.y_bin.as_float();
133-
if offset_x != 0.0 || offset_y != 0.0 {
134-
transform = transform.post_translate(offset_x, offset_y);
135-
}
135+
resvg::render(svg, transform, &mut pixmap.as_mut());
136136

137-
resvg::render(svg, transform, &mut pixmap.as_mut());
137+
let data: Vec<u8> = if let ContentType::Mask = content_type {
138+
// Only use the alpha channel for symbolic icons.
139+
pixmap.data().iter().skip(3).step_by(4).copied().collect()
140+
} else {
141+
pixmap.data().to_vec()
142+
};
138143

139-
let data: Vec<u8> = if let ContentType::Mask = content_type {
140-
// Only use the alpha channel for symbolic icons.
141-
pixmap.data().iter().skip(3).step_by(4).copied().collect()
142-
} else {
143-
pixmap.data().to_vec()
144+
Some(RasterizedCustomGlyph { data, content_type })
144145
};
145146

146-
Some(RasterizedCustomGlyph { data, content_type })
147-
};
148-
149147
Self {
150148
device,
151149
queue,

examples/text-sizes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ impl winit::application::ApplicationHandler for Application {
244244
bottom: top.floor() as i32 + physical_size.height,
245245
},
246246
default_color: FONT_COLOR,
247+
custom_glyphs: &[],
247248
};
248249

249250
let total_lines = b

src/cache.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
use crate::{GlyphToRender, Params};
2-
2+
use std::{
3+
borrow::Cow,
4+
mem,
5+
num::NonZeroU64,
6+
ops::Deref,
7+
sync::{Arc, RwLock},
8+
};
39
use wgpu::{
410
BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutEntry,
511
BindingResource, BindingType, BlendState, Buffer, BufferBindingType, ColorTargetState,
@@ -10,12 +16,8 @@ use wgpu::{
1016
TextureFormat, TextureSampleType, TextureView, TextureViewDimension, VertexFormat, VertexState,
1117
};
1218

13-
use std::borrow::Cow;
14-
use std::mem;
15-
use std::num::NonZeroU64;
16-
use std::ops::Deref;
17-
use std::sync::{Arc, RwLock};
18-
19+
/// A cache to share common resources (e.g., pipelines, layouts, shaders) between multiple text
20+
/// renderers.
1921
#[derive(Debug, Clone)]
2022
pub struct Cache(Arc<Inner>);
2123

@@ -38,6 +40,7 @@ struct Inner {
3840
}
3941

4042
impl Cache {
43+
/// Creates a new `Cache` with the given `device`.
4144
pub fn new(device: &Device) -> Self {
4245
let sampler = device.create_sampler(&SamplerDescriptor {
4346
label: Some("glyphon sampler"),

src/custom_glyph.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct CustomGlyph {
1919
/// The color of this glyph (only relevant if the glyph is rendered with the
2020
/// type [`ContentType::Mask`])
2121
///
22-
/// Set to `None` to use [`TextArea::default_color`].
22+
/// Set to `None` to use [`crate::TextArea::default_color`].
2323
pub color: Option<Color>,
2424
/// If `true`, then this glyph will be snapped to the nearest whole physical
2525
/// pixel and the resulting `SubpixelBin`'s in `RasterizationRequest` will always
@@ -31,7 +31,7 @@ pub struct CustomGlyph {
3131

3232
/// A request to rasterize a custom glyph
3333
#[derive(Debug, Clone, Copy, PartialEq)]
34-
pub struct RasterizationRequest {
34+
pub struct RasterizeCustomGlyphRequest {
3535
/// The unique identifier of the glyph
3636
pub id: CustomGlyphId,
3737
/// The width of the glyph in physical pixels
@@ -63,7 +63,11 @@ pub struct RasterizedCustomGlyph {
6363
}
6464

6565
impl RasterizedCustomGlyph {
66-
pub(crate) fn validate(&self, input: &RasterizationRequest, expected_type: Option<ContentType>) {
66+
pub(crate) fn validate(
67+
&self,
68+
input: &RasterizeCustomGlyphRequest,
69+
expected_type: Option<ContentType>,
70+
) {
6771
if let Some(expected_type) = expected_type {
6872
assert_eq!(self.content_type, expected_type, "Custom glyph rasterizer must always produce the same content type for a given input. Expected {:?}, got {:?}. Input: {:?}", expected_type, self.content_type, input);
6973
}

src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod viewport;
1313

1414
pub use cache::Cache;
1515
pub use custom_glyph::{
16-
ContentType, CustomGlyph, CustomGlyphId, RasterizationRequest, RasterizedCustomGlyph,
16+
ContentType, CustomGlyph, CustomGlyphId, RasterizeCustomGlyphRequest, RasterizedCustomGlyph,
1717
};
1818
pub use error::{PrepareError, RenderError};
1919
pub use text_atlas::{ColorMode, TextAtlas};
@@ -117,9 +117,8 @@ pub struct TextArea<'a> {
117117
/// The visible bounds of the text area. This is used to clip the text and doesn't have to
118118
/// match the `left` and `top` values.
119119
pub bounds: TextBounds,
120-
// The default color of the text area.
120+
/// The default color of the text area.
121121
pub default_color: Color,
122-
123-
/// Additional custom glyphs to render
122+
/// Additional custom glyphs to render.
124123
pub custom_glyphs: &'a [CustomGlyph],
125124
}

src/text_atlas.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
text_render::GlyphonCacheKey, Cache, ContentType, RasterizationRequest, RasterizedCustomGlyph,
3-
FontSystem, GlyphDetails, GpuCacheStatus, SwashCache,
2+
text_render::GlyphonCacheKey, Cache, ContentType, RasterizeCustomGlyphRequest, FontSystem,
3+
GlyphDetails, GpuCacheStatus, RasterizedCustomGlyph, SwashCache,
44
};
55
use etagere::{size2, Allocation, BucketedAtlasAllocator};
66
use lru::LruCache;
@@ -124,7 +124,9 @@ impl InnerAtlas {
124124
font_system: &mut FontSystem,
125125
cache: &mut SwashCache,
126126
scale_factor: f32,
127-
mut rasterize_custom_glyph: impl FnMut(RasterizationRequest) -> Option<RasterizedCustomGlyph>,
127+
mut rasterize_custom_glyph: impl FnMut(
128+
RasterizeCustomGlyphRequest,
129+
) -> Option<RasterizedCustomGlyph>,
128130
) -> bool {
129131
if self.size >= self.max_texture_dimension_2d {
130132
return false;
@@ -169,7 +171,7 @@ impl InnerAtlas {
169171
(image.data, width, height)
170172
}
171173
GlyphonCacheKey::Custom(cache_key) => {
172-
let input = RasterizationRequest {
174+
let input = RasterizeCustomGlyphRequest {
173175
id: cache_key.glyph_id,
174176
width: cache_key.width,
175177
height: cache_key.height,
@@ -264,7 +266,7 @@ impl Kind {
264266
}
265267
}
266268

267-
/// The color mode of an [`Atlas`].
269+
/// The color mode of a [`TextAtlas`].
268270
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269271
pub enum ColorMode {
270272
/// Accurate color management.
@@ -352,7 +354,9 @@ impl TextAtlas {
352354
cache: &mut SwashCache,
353355
content_type: ContentType,
354356
scale_factor: f32,
355-
rasterize_custom_glyph: impl FnMut(RasterizationRequest) -> Option<RasterizedCustomGlyph>,
357+
rasterize_custom_glyph: impl FnMut(
358+
RasterizeCustomGlyphRequest,
359+
) -> Option<RasterizedCustomGlyph>,
356360
) -> bool {
357361
let did_grow = match content_type {
358362
ContentType::Mask => self.mask_atlas.grow(

src/text_render.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
2-
custom_glyph::CustomGlyphCacheKey, ColorMode, ContentType, RasterizationRequest, RasterizedCustomGlyph,
3-
FontSystem, GlyphDetails, GlyphToRender, GpuCacheStatus, PrepareError, RenderError, SwashCache,
4-
SwashContent, TextArea, TextAtlas, Viewport,
2+
custom_glyph::CustomGlyphCacheKey, ColorMode, ContentType, FontSystem, GlyphDetails,
3+
GlyphToRender, GpuCacheStatus, PrepareError, RasterizeCustomGlyphRequest,
4+
RasterizedCustomGlyph, RenderError, SwashCache, SwashContent, TextArea, TextAtlas, Viewport,
55
};
66
use cosmic_text::{Color, SubpixelBin};
77
use std::{slice, sync::Arc};
@@ -104,7 +104,7 @@ impl TextRenderer {
104104
viewport: &Viewport,
105105
text_areas: impl IntoIterator<Item = TextArea<'a>>,
106106
cache: &mut SwashCache,
107-
rasterize_custom_glyph: impl FnMut(RasterizationRequest) -> Option<RasterizedCustomGlyph>,
107+
rasterize_custom_glyph: impl FnMut(RasterizeCustomGlyphRequest) -> Option<RasterizedCustomGlyph>,
108108
) -> Result<(), PrepareError> {
109109
self.prepare_with_depth_and_custom(
110110
device,
@@ -130,7 +130,9 @@ impl TextRenderer {
130130
text_areas: impl IntoIterator<Item = TextArea<'a>>,
131131
cache: &mut SwashCache,
132132
mut metadata_to_depth: impl FnMut(usize) -> f32,
133-
mut rasterize_custom_glyph: impl FnMut(RasterizationRequest) -> Option<RasterizedCustomGlyph>,
133+
mut rasterize_custom_glyph: impl FnMut(
134+
RasterizeCustomGlyphRequest,
135+
) -> Option<RasterizedCustomGlyph>,
134136
) -> Result<(), PrepareError> {
135137
self.glyph_vertices.clear();
136138

@@ -193,7 +195,7 @@ impl TextRenderer {
193195
return None;
194196
}
195197

196-
let input = RasterizationRequest {
198+
let input = RasterizeCustomGlyphRequest {
197199
id: glyph.id,
198200
width,
199201
height,
@@ -202,9 +204,7 @@ impl TextRenderer {
202204
scale: text_area.scale,
203205
};
204206

205-
let Some(output) = (rasterize_custom_glyph)(input) else {
206-
return None;
207-
};
207+
let output = (rasterize_custom_glyph)(input)?;
208208

209209
output.validate(&input, None);
210210

@@ -268,11 +268,8 @@ impl TextRenderer {
268268
font_system,
269269
_rasterize_custom_glyph|
270270
-> Option<GetGlyphImageResult> {
271-
let Some(image) =
272-
cache.get_image_uncached(font_system, physical_glyph.cache_key)
273-
else {
274-
return None;
275-
};
271+
let image =
272+
cache.get_image_uncached(font_system, physical_glyph.cache_key)?;
276273

277274
let content_type = match image.content {
278275
SwashContent::Color => ContentType::Color,
@@ -429,7 +426,7 @@ fn prepare_glyph<R>(
429426
mut rasterize_custom_glyph: R,
430427
) -> Result<Option<GlyphToRender>, PrepareError>
431428
where
432-
R: FnMut(RasterizationRequest) -> Option<RasterizedCustomGlyph>,
429+
R: FnMut(RasterizeCustomGlyphRequest) -> Option<RasterizedCustomGlyph>,
433430
{
434431
if atlas.mask_atlas.glyph_cache.contains(&cache_key) {
435432
atlas.mask_atlas.promote(cache_key);

src/viewport.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use crate::{Cache, Params, Resolution};
2-
2+
use std::{mem, slice};
33
use wgpu::{BindGroup, Buffer, BufferDescriptor, BufferUsages, Device, Queue};
44

5-
use std::mem;
6-
use std::slice;
7-
5+
/// Controls the visible area of all text for a given renderer. Any text outside of the visible
6+
/// area will be clipped.
7+
///
8+
/// Many projects will only ever need a single `Viewport`, but it is possible to create multiple
9+
/// `Viewport`s if you want to render text to specific areas within a window (without having to)
10+
/// bound each `TextArea`).
811
#[derive(Debug)]
912
pub struct Viewport {
1013
params: Params,
@@ -13,6 +16,7 @@ pub struct Viewport {
1316
}
1417

1518
impl Viewport {
19+
/// Creates a new `Viewport` with the given `device` and `cache`.
1620
pub fn new(device: &Device, cache: &Cache) -> Self {
1721
let params = Params {
1822
screen_resolution: Resolution {
@@ -38,6 +42,7 @@ impl Viewport {
3842
}
3943
}
4044

45+
/// Updates the `Viewport` with the given `resolution`.
4146
pub fn update(&mut self, queue: &Queue, resolution: Resolution) {
4247
if self.params.screen_resolution != resolution {
4348
self.params.screen_resolution = resolution;
@@ -51,6 +56,7 @@ impl Viewport {
5156
}
5257
}
5358

59+
/// Returns the current resolution of the `Viewport`.
5460
pub fn resolution(&self) -> Resolution {
5561
self.params.screen_resolution
5662
}

0 commit comments

Comments
 (0)