1use std::rc::Rc;
4
5use bitflags::bitflags;
6use widestring::U16String;
7
8use crate::legacy::{
9 collision_feature::CollisionFeature,
10 geometry::{anchor::Anchor, feature_index::IndexedSubfeature},
11 geometry_tile_data::GeometryCoordinates,
12 glyph::{Shaping, WritingModeType},
13 image::ImageMap,
14 quads::{get_glyph_quads, get_icon_quads, SymbolQuads},
15 shaping::PositionedIcon,
16 style_types::{SymbolLayoutProperties_Evaluated, SymbolPlacementType},
17};
18
19fn get_any_shaping(shaped_text_orientations: &ShapedTextOrientations) -> &Shaping {
21 if shaped_text_orientations.right().is_any_line_not_empty() {
22 return shaped_text_orientations.right();
23 }
24 if shaped_text_orientations.center.is_any_line_not_empty() {
25 return &(shaped_text_orientations.center);
26 }
27 if shaped_text_orientations.left.is_any_line_not_empty() {
28 return &(shaped_text_orientations.left);
29 }
30 if shaped_text_orientations.vertical.is_any_line_not_empty() {
31 return &(shaped_text_orientations.vertical);
32 }
33 &shaped_text_orientations.horizontal
34}
35
36#[derive(Default)]
38pub struct ShapedTextOrientations {
39 horizontal: Shaping,
40 vertical: Shaping,
41 center: Shaping,
43 left: Shaping,
44 pub single_line: bool,
45}
46
47impl ShapedTextOrientations {
48 pub fn new(
50 horizontal: Shaping,
51 vertical: Shaping,
52 right: Option<Shaping>,
53 center: Shaping,
54 left: Shaping,
55 single_line: bool,
56 ) -> Self {
57 Self {
58 horizontal: (horizontal),
59 vertical: (vertical),
60 center: (center),
61 left: (left),
62 single_line: single_line,
63 }
64 }
65
66 pub fn horizontal(&self) -> &Shaping {
68 &self.horizontal
69 }
70 pub fn vertical(&self) -> &Shaping {
72 &self.vertical
73 }
74 pub fn right(&self) -> &Shaping {
76 &self.horizontal
77 }
78 pub fn center(&self) -> &Shaping {
80 &self.center
81 }
82 pub fn left(&self) -> &Shaping {
84 &self.left
85 }
86
87 pub fn set_horizontal(&mut self, horizontal: Shaping) {
89 self.horizontal = horizontal;
90 }
91 pub fn set_vertical(&mut self, vertical: Shaping) {
93 self.vertical = vertical;
94 }
95}
96
97bitflags! {
98 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
100 pub struct SymbolContent: u8 {
101 const None = 0;
102 const Text = 1 << 0;
103 const IconRGBA = 1 << 1;
104 const IconSDF = 1 << 2;
105 }
106}
107
108#[derive(Default)]
110pub struct SymbolInstanceSharedData {
111 line: GeometryCoordinates,
112 right_justified_glyph_quads: SymbolQuads,
114 center_justified_glyph_quads: SymbolQuads,
115 left_justified_glyph_quads: SymbolQuads,
116 vertical_glyph_quads: SymbolQuads,
117 icon_quads: Option<SymbolQuads>,
118 vertical_icon_quads: Option<SymbolQuads>,
119}
120
121impl SymbolInstanceSharedData {
122 pub fn new(
124 line_: GeometryCoordinates,
125 shaped_text_orientations: &ShapedTextOrientations,
126 shaped_icon: Option<PositionedIcon>,
127 vertically_shaped_icon: Option<PositionedIcon>,
128 layout: &SymbolLayoutProperties_Evaluated,
129 text_placement: SymbolPlacementType,
130 text_offset: [f64; 2],
131 image_map: &ImageMap,
132 icon_rotation: f64,
133 icon_type: SymbolContent,
134 has_icon_text_fit: bool,
135 allow_vertical_placement: bool,
136 ) -> Self {
137 let mut self_ = Self {
138 line: line_,
139 ..Self::default()
140 };
141 if let Some(shaped_icon) = &shaped_icon {
143 self_.icon_quads = Some(get_icon_quads(
144 shaped_icon,
145 icon_rotation,
146 icon_type,
147 has_icon_text_fit,
148 ));
149 if let Some(vertically_shaped_icon) = &vertically_shaped_icon {
150 self_.vertical_icon_quads = Some(get_icon_quads(
151 vertically_shaped_icon,
152 icon_rotation,
153 icon_type,
154 has_icon_text_fit,
155 ));
156 }
157 }
158
159 if !shaped_text_orientations.single_line {
161 if shaped_text_orientations.right().is_any_line_not_empty() {
162 self_.right_justified_glyph_quads = get_glyph_quads(
163 shaped_text_orientations.right(),
164 text_offset,
165 layout,
166 text_placement,
167 image_map,
168 allow_vertical_placement,
169 );
170 }
171
172 if shaped_text_orientations.center.is_any_line_not_empty() {
173 self_.center_justified_glyph_quads = get_glyph_quads(
174 &shaped_text_orientations.center,
175 text_offset,
176 layout,
177 text_placement,
178 image_map,
179 allow_vertical_placement,
180 );
181 }
182
183 if shaped_text_orientations.left.is_any_line_not_empty() {
184 self_.left_justified_glyph_quads = get_glyph_quads(
185 &shaped_text_orientations.left,
186 text_offset,
187 layout,
188 text_placement,
189 image_map,
190 allow_vertical_placement,
191 );
192 }
193 } else {
194 let shape = if shaped_text_orientations.right().is_any_line_not_empty() {
195 Some(shaped_text_orientations.right())
196 } else if shaped_text_orientations.center.is_any_line_not_empty() {
197 Some(&shaped_text_orientations.center)
198 } else if shaped_text_orientations.left.is_any_line_not_empty() {
199 Some(&shaped_text_orientations.left)
200 } else {
201 None
202 };
203
204 if let Some(shape) = shape {
205 self_.right_justified_glyph_quads = get_glyph_quads(
206 shape,
207 text_offset,
208 layout,
209 text_placement,
210 image_map,
211 allow_vertical_placement,
212 );
213 }
214 }
215
216 if shaped_text_orientations.vertical.is_any_line_not_empty() {
217 self_.vertical_glyph_quads = get_glyph_quads(
218 &shaped_text_orientations.vertical,
219 text_offset,
220 layout,
221 text_placement,
222 image_map,
223 allow_vertical_placement,
224 );
225 }
226 self_
227 }
228 fn empty(&self) -> bool {
230 self.right_justified_glyph_quads.is_empty()
231 && self.center_justified_glyph_quads.is_empty()
232 && self.left_justified_glyph_quads.is_empty()
233 && self.vertical_glyph_quads.is_empty()
234 }
235}
236
237#[derive(Clone)]
239pub struct SymbolInstance {
240 shared_data: Rc<SymbolInstanceSharedData>,
241
242 pub anchor: Anchor,
243 pub symbol_content: SymbolContent,
244
245 pub right_justified_glyph_quads_size: usize,
246 pub center_justified_glyph_quads_size: usize,
247 pub left_justified_glyph_quads_size: usize,
248 pub vertical_glyph_quads_size: usize,
249 pub icon_quads_size: usize,
250
251 pub text_collision_feature: CollisionFeature,
252 pub icon_collision_feature: CollisionFeature,
253 pub vertical_text_collision_feature: Option<CollisionFeature>,
254 pub vertical_icon_collision_feature: Option<CollisionFeature>,
255 pub writing_modes: WritingModeType,
256 pub layout_feature_index: usize, pub data_feature_index: usize, pub text_offset: [f64; 2],
259 pub icon_offset: [f64; 2],
260 pub key: U16String,
261 pub placed_right_text_index: Option<usize>,
262 pub placed_center_text_index: Option<usize>,
263 pub placed_left_text_index: Option<usize>,
264 pub placed_vertical_text_index: Option<usize>,
265 pub placed_icon_index: Option<usize>,
266 pub placed_vertical_icon_index: Option<usize>,
267 pub text_box_scale: f64,
268 pub variable_text_offset: [f64; 2],
269 pub single_line: bool,
270 pub cross_tile_id: u32,
271}
272
273impl SymbolInstance {
274 pub fn new(
276 anchor_: Anchor,
277 shared_data: Rc<SymbolInstanceSharedData>,
278 shaped_text_orientations: &ShapedTextOrientations,
279 shaped_icon: &Option<PositionedIcon>,
280 vertically_shaped_icon: &Option<PositionedIcon>,
281 text_box_scale: f64,
282 text_padding: f64,
283 text_placement: SymbolPlacementType,
284 text_offset: [f64; 2],
285 icon_box_scale: f64,
286 icon_padding: f64,
287 icon_offset: [f64; 2],
288 indexed_feature: IndexedSubfeature,
289 layout_feature_index: usize,
290 data_feature_index: usize,
291 key_: U16String,
292 overscaling: f64,
293 icon_rotation: f64,
294 text_rotation: f64,
295 variable_text_offset: [f64; 2],
296 allow_vertical_placement: bool,
297 icon_type: SymbolContent,
298 ) -> Self {
299 let mut self_ = Self {
300 symbol_content: icon_type,
301 text_collision_feature: CollisionFeature::new_from_text(
305 &shared_data.line,
306 &anchor_,
307 get_any_shaping(shaped_text_orientations).clone(),
308 text_box_scale,
309 text_padding,
310 text_placement,
311 indexed_feature.clone(),
312 overscaling,
313 text_rotation,
314 ),
315 icon_collision_feature: CollisionFeature::new_from_icon(
316 &shared_data.line,
317 &anchor_,
318 shaped_icon,
319 icon_box_scale,
320 icon_padding,
321 indexed_feature.clone(),
322 icon_rotation,
323 ),
324
325 shared_data: shared_data,
326 anchor: anchor_,
327 writing_modes: WritingModeType::None,
328 layout_feature_index: layout_feature_index,
329 data_feature_index: data_feature_index,
330 text_offset: text_offset,
331 icon_offset: icon_offset,
332 key: key_,
333
334 text_box_scale: text_box_scale,
335 variable_text_offset: variable_text_offset,
336 single_line: shaped_text_orientations.single_line,
337
338 right_justified_glyph_quads_size: 0,
339 center_justified_glyph_quads_size: 0,
340 left_justified_glyph_quads_size: 0,
341 vertical_glyph_quads_size: 0,
342 icon_quads_size: 0,
343
344 vertical_text_collision_feature: None,
345 placed_right_text_index: None,
346 placed_center_text_index: None,
347 placed_left_text_index: None,
348 placed_vertical_text_index: None,
349 placed_icon_index: None,
350 placed_vertical_icon_index: None,
351
352 vertical_icon_collision_feature: None,
353 cross_tile_id: 0,
354 };
355
356 if !self_.shared_data.empty() {
358 self_.symbol_content |= SymbolContent::Text;
359 }
360 if allow_vertical_placement && shaped_text_orientations.vertical.is_any_line_not_empty() {
361 let vertical_point_label_angle = 90.0;
362 self_.vertical_text_collision_feature = Some(CollisionFeature::new_from_text(
363 self_.line(),
364 &self_.anchor,
365 shaped_text_orientations.vertical.clone(),
366 text_box_scale,
367 text_padding,
368 text_placement,
369 indexed_feature.clone(),
370 overscaling,
371 text_rotation + vertical_point_label_angle,
372 ));
373 if vertically_shaped_icon.is_some() {
374 self_.vertical_icon_collision_feature = Some(CollisionFeature::new_from_icon(
375 &self_.shared_data.line,
376 &self_.anchor,
377 vertically_shaped_icon,
378 icon_box_scale,
379 icon_padding,
380 indexed_feature,
381 icon_rotation + vertical_point_label_angle,
382 ));
383 }
384 }
385
386 self_.right_justified_glyph_quads_size =
387 self_.shared_data.right_justified_glyph_quads.len();
388 self_.center_justified_glyph_quads_size =
389 self_.shared_data.center_justified_glyph_quads.len();
390 self_.left_justified_glyph_quads_size = self_.shared_data.left_justified_glyph_quads.len();
391 self_.vertical_glyph_quads_size = self_.shared_data.vertical_glyph_quads.len();
392
393 self_.icon_quads_size = if let Some(icon_quads) = &self_.shared_data.icon_quads {
394 icon_quads.len()
395 } else {
396 0
397 };
398
399 if self_.right_justified_glyph_quads_size != 0
400 || self_.center_justified_glyph_quads_size != 0
401 || self_.left_justified_glyph_quads_size != 0
402 {
403 self_.writing_modes |= WritingModeType::Horizontal;
404 }
405
406 if self_.vertical_glyph_quads_size != 0 {
407 self_.writing_modes |= WritingModeType::Vertical;
408 }
409
410 self_
411 }
412 pub fn get_default_horizontal_placed_text_index(&self) -> Option<usize> {
414 if let Some(index) = self.placed_right_text_index {
415 return Some(index);
416 }
417 if let Some(index) = self.placed_center_text_index {
418 return Some(index);
419 }
420 if let Some(index) = self.placed_left_text_index {
421 return Some(index);
422 }
423 None
424 }
425 pub fn line(&self) -> &GeometryCoordinates {
427 &self.shared_data.line
428 }
429 pub fn right_justified_glyph_quads(&self) -> &SymbolQuads {
431 &self.shared_data.right_justified_glyph_quads
432 }
433 pub fn left_justified_glyph_quads(&self) -> &SymbolQuads {
435 &self.shared_data.left_justified_glyph_quads
436 }
437 pub fn center_justified_glyph_quads(&self) -> &SymbolQuads {
439 &self.shared_data.center_justified_glyph_quads
440 }
441 pub fn vertical_glyph_quads(&self) -> &SymbolQuads {
443 &self.shared_data.vertical_glyph_quads
444 }
445 pub fn has_text(&self) -> bool {
447 self.symbol_content.contains(SymbolContent::Text) }
449 pub fn has_icon(&self) -> bool {
451 self.symbol_content.contains(SymbolContent::IconRGBA) || self.has_sdf_icon()
452 }
453 pub fn has_sdf_icon(&self) -> bool {
455 self.symbol_content.contains(SymbolContent::IconSDF)
456 }
457 pub fn icon_quads(&self) -> &Option<SymbolQuads> {
459 &self.shared_data.icon_quads
460 }
461 pub fn vertical_icon_quads(&self) -> &Option<SymbolQuads> {
463 &self.shared_data.vertical_icon_quads
464 }
465 pub fn release_shared_data(&self) {
467 }
470
471 fn invalid_cross_tile_id() -> u32 {
473 u32::MAX
474 }
475}
476
477type SymbolInstanceReferences = Vec<SymbolInstance>;