Skip to main content

lumen_text/
gpu.rs

1use bytemuck::{Pod, Zeroable};
2use cosmic_text::{SwashContent, SwashImage};
3
4#[cfg(feature = "experimental-msdf")]
5use crate::MsdfGlyphPlacement;
6use crate::{AtlasEntry, TextGlyph};
7
8const GLYPH_MODE_RASTER_MASK: u32 = 0;
9const GLYPH_MODE_RASTER_COLOR: u32 = 1;
10#[cfg(feature = "experimental-msdf")]
11const GLYPH_MODE_MSDF: u32 = 2;
12
13#[repr(C)]
14#[derive(Debug, Clone, Copy, Pod, Zeroable)]
15pub struct GpuTextGlobals {
16    pub target_size: [f32; 2],
17    pub px_range: f32,
18    pub glyph_count: u32,
19}
20
21#[repr(C)]
22#[derive(Debug, Clone, Copy, Pod, Zeroable)]
23pub struct GpuGlyphInstance {
24    pub rect: [f32; 4],
25    pub uv_rect: [f32; 4],
26    pub color: [f32; 4],
27    pub mode: u32,
28    pub _padding: [u32; 3],
29}
30
31#[cfg(feature = "experimental-msdf")]
32#[repr(C)]
33#[derive(Debug, Clone, Copy, Pod, Zeroable)]
34pub struct GpuMsdfGlobals {
35    pub atlas_size: [u32; 2],
36    pub job_count: u32,
37    pub dirty_pixel_count: u32,
38    pub _padding: [u32; 2],
39}
40
41#[cfg(feature = "experimental-msdf")]
42#[repr(C)]
43#[derive(Debug, Clone, Copy, Pod, Zeroable)]
44pub struct GpuMsdfJob {
45    pub atlas_rect: [u32; 4],
46    pub segment_range: [u32; 2],
47    pub pixel_range: [u32; 2],
48    pub px_range: f32,
49    pub _padding: [u32; 3],
50}
51
52#[cfg(feature = "experimental-msdf")]
53#[repr(C)]
54#[derive(Debug, Clone, Copy, Pod, Zeroable)]
55pub struct GpuMsdfSegment {
56    pub p0: [f32; 2],
57    pub p1: [f32; 2],
58    pub p2: [f32; 2],
59    pub p3: [f32; 2],
60    pub kind: u32,
61    pub channels: u32,
62    pub _padding: [u32; 2],
63}
64
65pub fn glyph_instance_for(
66    glyph: &TextGlyph,
67    atlas_entry: AtlasEntry,
68    image: &SwashImage,
69) -> GpuGlyphInstance {
70    let x = glyph.x + image.placement.left as f32;
71    let y = glyph.y - image.placement.top as f32;
72    GpuGlyphInstance {
73        rect: [
74            x,
75            y,
76            image.placement.width as f32,
77            image.placement.height as f32,
78        ],
79        uv_rect: [
80            atlas_entry.uv_min[0],
81            atlas_entry.uv_min[1],
82            atlas_entry.uv_max[0],
83            atlas_entry.uv_max[1],
84        ],
85        color: glyph.color,
86        mode: if image.content == SwashContent::Color {
87            GLYPH_MODE_RASTER_COLOR
88        } else {
89            GLYPH_MODE_RASTER_MASK
90        },
91        _padding: [0; 3],
92    }
93}
94
95#[cfg(feature = "experimental-msdf")]
96pub fn msdf_glyph_instance_for(
97    glyph: &TextGlyph,
98    atlas_entry: AtlasEntry,
99    placement: &MsdfGlyphPlacement,
100) -> GpuGlyphInstance {
101    let x = glyph.x + placement.left;
102    let y = glyph.y - placement.top;
103    GpuGlyphInstance {
104        rect: [x, y, placement.width as f32, placement.height as f32],
105        uv_rect: [
106            atlas_entry.uv_min[0],
107            atlas_entry.uv_min[1],
108            atlas_entry.uv_max[0],
109            atlas_entry.uv_max[1],
110        ],
111        color: glyph.color,
112        mode: GLYPH_MODE_MSDF,
113        _padding: [0; 3],
114    }
115}
116
117#[cfg(feature = "experimental-msdf")]
118pub fn is_msdf_instance(instance: &GpuGlyphInstance) -> bool {
119    instance.mode == GLYPH_MODE_MSDF
120}