1use std::{
2 marker::PhantomData,
3 ops::{Deref, Range},
4 rc::Rc,
5};
6
7use crate::{
8 coords::WorldTileCoords,
9 environment::Environment,
10 euclid::{Box2D, Point2D},
11 kernel::Kernel,
12 legacy::TileSpace,
13 plugin::Plugin,
14 render::{
15 eventually::Eventually,
16 graph::RenderGraph,
17 shaders::{
18 SDFShaderFeatureMetadata, ShaderLayerMetadata, ShaderSymbolVertex,
19 ShaderSymbolVertexNew,
20 },
21 RenderStageLabel,
22 },
23 schedule::Schedule,
24 sdf::resource::GlyphTexture,
25 tcs::{system::SystemContainer, tiles::TileComponent, world::World},
26 vector::{
27 resource::BufferPool,
28 tessellation::{IndexDataType, OverAlignedVertexBuffer},
29 VectorTransferables,
30 },
31};
32
33pub mod collision_system;
34mod populate_world_system;
35mod queue_system;
36mod render_commands;
37mod resource;
38mod resource_system;
39mod upload_system;
40
41pub mod tessellation;
42pub mod tessellation_new;
43pub mod text;
44
45struct SymbolPipeline(wgpu::RenderPipeline);
46
47impl Deref for SymbolPipeline {
48 type Target = wgpu::RenderPipeline;
49
50 fn deref(&self) -> &Self::Target {
51 &self.0
52 }
53}
54
55pub type SymbolBufferPool = BufferPool<
56 wgpu::Queue,
57 wgpu::Buffer,
58 ShaderSymbolVertexNew,
59 IndexDataType,
60 ShaderLayerMetadata,
61 SDFShaderFeatureMetadata,
62>;
63
64pub struct SdfPlugin<T>(PhantomData<T>);
65
66impl<T: VectorTransferables> Default for SdfPlugin<T> {
67 fn default() -> Self {
68 Self(Default::default())
69 }
70}
71
72impl<E: Environment, T: VectorTransferables> Plugin<E> for SdfPlugin<T> {
73 fn build(
74 &self,
75 schedule: &mut Schedule,
76 kernel: Rc<Kernel<E>>,
77 world: &mut World,
78 _graph: &mut RenderGraph,
79 ) {
80 let resources = &mut world.resources;
81
82 resources.insert(Eventually::<SymbolPipeline>::Uninitialized);
83 resources.insert(Eventually::<SymbolBufferPool>::Uninitialized);
84 resources.insert(Eventually::<GlyphTexture>::Uninitialized);
85 resources.insert(Eventually::<(wgpu::Texture, wgpu::Sampler)>::Uninitialized);
86
87 schedule.add_system_to_stage(
88 RenderStageLabel::Extract,
89 SystemContainer::new(populate_world_system::PopulateWorldSystem::<E, T>::new(
90 &kernel,
91 )),
92 );
93
94 schedule.add_system_to_stage(RenderStageLabel::Prepare, resource_system::resource_system);
95 schedule.add_system_to_stage(RenderStageLabel::Queue, upload_system::upload_system); schedule.add_system_to_stage(RenderStageLabel::Queue, queue_system::queue_system);
97
98 schedule.add_system_to_stage(
99 RenderStageLabel::PhaseSort,
100 SystemContainer::new(collision_system::CollisionSystem::new()),
101 );
102 }
103}
104
105pub struct Feature {
106 pub bbox: Box2D<f32, TileSpace>,
107 pub indices: Range<usize>,
108 pub text_anchor: Point2D<f32, TileSpace>,
109 pub str: String,
110}
111
112pub struct SymbolLayerData {
113 pub coords: WorldTileCoords,
114 pub source_layer: String,
115 pub style_layer_id: String,
116 pub buffer: OverAlignedVertexBuffer<ShaderSymbolVertex, IndexDataType>,
117 pub new_buffer: OverAlignedVertexBuffer<ShaderSymbolVertexNew, IndexDataType>, pub features: Vec<Feature>,
119}
120
121#[derive(Default)]
122pub struct SymbolLayersDataComponent {
123 pub layers: Vec<SymbolLayerData>,
124}
125
126impl TileComponent for SymbolLayersDataComponent {}
127
128#[cfg(test)]
129mod tests {
130 use std::collections::HashMap;
131
132 use crate::{
133 euclid::{Point2D, Rect, Size2D},
134 legacy::{
135 bidi::Char16,
136 font_stack::FontStackHasher,
137 geometry_tile_data::{GeometryCoordinates, SymbolGeometryTileLayer},
138 glyph::{Glyph, GlyphDependencies, GlyphMap, GlyphMetrics, Glyphs},
139 glyph_atlas::{GlyphPosition, GlyphPositionMap, GlyphPositions},
140 image::ImageMap,
141 image_atlas::ImagePositions,
142 layout::{
143 layout::{BucketParameters, LayerTypeInfo, LayoutParameters},
144 symbol_feature::{SymbolGeometryTileFeature, VectorGeometryTileFeature},
145 symbol_layout::{FeatureIndex, LayerProperties, SymbolLayer, SymbolLayout},
146 },
147 style_types::SymbolLayoutProperties_Unevaluated,
148 CanonicalTileID, MapMode, OverscaledTileID,
149 },
150 };
151
152 #[test]
153 fn test() {
154 let fontStack = vec![
155 "Open Sans Regular".to_string(),
156 "Arial Unicode MS Regular".to_string(),
157 ];
158
159 let mut glyphDependencies = GlyphDependencies::new();
160
161 let tile_id = OverscaledTileID {
162 canonical: CanonicalTileID { x: 0, y: 0, z: 0 },
163 overscaled_z: 0,
164 };
165 let mut parameters = BucketParameters {
166 tile_id: tile_id,
167 mode: MapMode::Continuous,
168 pixel_ratio: 1.0,
169 layer_type: LayerTypeInfo,
170 };
171 let mut layout = SymbolLayout::new(
172 ¶meters,
173 &vec![LayerProperties {
174 id: "layer".to_string(),
175 layer: SymbolLayer {
176 layout: SymbolLayoutProperties_Unevaluated,
177 },
178 }],
179 Box::new(SymbolGeometryTileLayer {
180 name: "layer".to_string(),
181 features: vec![SymbolGeometryTileFeature::new(Box::new(
182 VectorGeometryTileFeature {
183 geometry: vec![GeometryCoordinates(vec![Point2D::new(1024, 1024)])],
184 },
185 ))],
186 }),
187 &mut LayoutParameters {
188 bucket_parameters: &mut parameters.clone(),
189 glyph_dependencies: &mut glyphDependencies,
190 image_dependencies: &mut Default::default(),
191 available_images: &mut Default::default(),
192 },
193 )
194 .unwrap();
195
196 assert_eq!(glyphDependencies.len(), 1);
197
198 let image_positions = ImagePositions::new();
201
202 let mut glyphPosition = GlyphPosition {
203 rect: Rect::new(Point2D::new(0, 0), Size2D::new(10, 10)),
204 metrics: GlyphMetrics {
205 width: 18,
206 height: 18,
207 left: 2,
208 top: -8,
209 advance: 21,
210 },
211 };
212 let glyphPositions: GlyphPositions = GlyphPositions::from([(
213 FontStackHasher::new(&fontStack),
214 GlyphPositionMap::from([('中' as Char16, glyphPosition)]),
215 )]);
216
217 let mut glyph = Glyph::default();
218 glyph.id = '中' as Char16;
219 glyph.metrics = glyphPosition.metrics;
220
221 let glyphs: GlyphMap = GlyphMap::from([(
222 FontStackHasher::new(&fontStack),
223 Glyphs::from([('中' as Char16, Some(glyph))]),
224 )]);
225
226 let empty_image_map = ImageMap::new();
227 layout.prepare_symbols(&glyphs, &glyphPositions, &empty_image_map, &image_positions);
228
229 let mut output = HashMap::new();
230 layout.create_bucket(
231 image_positions,
232 Box::new(FeatureIndex),
233 &mut output,
234 false,
235 false,
236 &tile_id.canonical,
237 );
238
239 println!("{:#?}", output)
240 }
241}