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}