1use markup5ever::{expanded_name, local_name, ns, QualName};
4use std::collections::{HashMap, HashSet};
5use std::fmt;
6use std::sync::OnceLock;
7
8use crate::accept_language::UserLanguage;
9use crate::bbox::BoundingBox;
10use crate::cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
11use crate::css::{Declaration, Origin};
12use crate::document::AcquiredNodes;
13use crate::drawing_ctx::{DrawingCtx, Viewport};
14use crate::error::*;
15use crate::filter::Filter;
16use crate::filters::{
17 blend::FeBlend,
18 color_matrix::FeColorMatrix,
19 component_transfer::{FeComponentTransfer, FeFuncA, FeFuncB, FeFuncG, FeFuncR},
20 composite::FeComposite,
21 convolve_matrix::FeConvolveMatrix,
22 displacement_map::FeDisplacementMap,
23 drop_shadow::FeDropShadow,
24 flood::FeFlood,
25 gaussian_blur::FeGaussianBlur,
26 image::FeImage,
27 lighting::{FeDiffuseLighting, FeDistantLight, FePointLight, FeSpecularLighting, FeSpotLight},
28 merge::{FeMerge, FeMergeNode},
29 morphology::FeMorphology,
30 offset::FeOffset,
31 tile::FeTile,
32 turbulence::FeTurbulence,
33 FilterEffect,
34};
35use crate::gradient::{LinearGradient, RadialGradient, Stop};
36use crate::image::Image;
37use crate::layout::Layer;
38use crate::marker::Marker;
39use crate::node::*;
40use crate::pattern::Pattern;
41use crate::properties::{ComputedValues, SpecifiedValues};
42use crate::rsvg_log;
43use crate::session::Session;
44use crate::shapes::{Circle, Ellipse, Line, Path, Polygon, Polyline, Rect};
45use crate::structure::{ClipPath, Group, Link, Mask, NonRendering, Svg, Switch, Symbol, Use};
46use crate::style::Style;
47use crate::text::{TRef, TSpan, Text};
48use crate::text2::Text2;
49use crate::xml::Attributes;
50
51pub type DrawResult = Result<Box<BoundingBox>, Box<InternalRenderingError>>;
52
53pub trait ElementTrait {
54 fn set_attributes(&mut self, _attributes: &Attributes, _session: &Session) {}
62
63 fn draw(
67 &self,
68 _node: &Node,
69 _acquired_nodes: &mut AcquiredNodes<'_>,
70 _cascaded: &CascadedValues<'_>,
71 viewport: &Viewport,
72 _draw_ctx: &mut DrawingCtx,
73 _clipping: bool,
74 ) -> DrawResult {
75 Ok(viewport.empty_bbox())
77 }
78
79 fn layout(
84 &self,
85 _node: &Node,
86 _acquired_nodes: &mut AcquiredNodes<'_>,
87 _cascaded: &CascadedValues<'_>,
88 _viewport: &Viewport,
89 _draw_ctx: &mut DrawingCtx,
90 _clipping: bool,
91 ) -> Result<Option<Layer>, Box<InternalRenderingError>> {
92 Ok(None)
93 }
94}
95
96pub fn set_attribute<T>(dest: &mut T, parse_result: Result<T, ElementError>, session: &Session) {
109 match parse_result {
110 Ok(v) => *dest = v,
111 Err(e) => {
112 rsvg_log!(session, "ignoring attribute with invalid value: {}", e);
115 }
116 }
117}
118
119pub struct Element {
120 element_name: QualName,
121 attributes: Attributes,
122 specified_values: SpecifiedValues,
123 important_styles: HashSet<QualName>,
124 values: ComputedValues,
125 required_extensions: Option<RequiredExtensions>,
126 required_features: Option<RequiredFeatures>,
127 system_language: Option<SystemLanguage>,
128 pub element_data: ElementData,
129}
130
131impl fmt::Display for Element {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(f, "{}", self.element_name().local)?;
134 write!(f, " id={}", self.get_id().unwrap_or("None"))?;
135 Ok(())
136 }
137}
138
139pub enum ElementData {
144 Circle(Box<Circle>),
145 ClipPath(Box<ClipPath>),
146 Ellipse(Box<Ellipse>),
147 Filter(Box<Filter>),
148 Group(Box<Group>),
149 Image(Box<Image>),
150 Line(Box<Line>),
151 LinearGradient(Box<LinearGradient>),
152 Link(Box<Link>),
153 Marker(Box<Marker>),
154 Mask(Box<Mask>),
155 NonRendering(Box<NonRendering>),
156 Path(Box<Path>),
157 Pattern(Box<Pattern>),
158 Polygon(Box<Polygon>),
159 Polyline(Box<Polyline>),
160 RadialGradient(Box<RadialGradient>),
161 Rect(Box<Rect>),
162 Stop(Box<Stop>),
163 Style(Box<Style>),
164 Svg(Box<Svg>),
165 Switch(Box<Switch>),
166 Symbol(Box<Symbol>),
167 Text(Box<Text>),
168 Text2(Box<Text2>),
169 TRef(Box<TRef>),
170 TSpan(Box<TSpan>),
171 Use(Box<Use>),
172
173 FeBlend(Box<FeBlend>),
175 FeColorMatrix(Box<FeColorMatrix>),
176 FeComponentTransfer(Box<FeComponentTransfer>),
177 FeComposite(Box<FeComposite>),
178 FeConvolveMatrix(Box<FeConvolveMatrix>),
179 FeDiffuseLighting(Box<FeDiffuseLighting>),
180 FeDisplacementMap(Box<FeDisplacementMap>),
181 FeDistantLight(Box<FeDistantLight>),
182 FeDropShadow(Box<FeDropShadow>),
183 FeFlood(Box<FeFlood>),
184 FeFuncA(Box<FeFuncA>),
185 FeFuncB(Box<FeFuncB>),
186 FeFuncG(Box<FeFuncG>),
187 FeFuncR(Box<FeFuncR>),
188 FeGaussianBlur(Box<FeGaussianBlur>),
189 FeImage(Box<FeImage>),
190 FeMerge(Box<FeMerge>),
191 FeMergeNode(Box<FeMergeNode>),
192 FeMorphology(Box<FeMorphology>),
193 FeOffset(Box<FeOffset>),
194 FePointLight(Box<FePointLight>),
195 FeSpecularLighting(Box<FeSpecularLighting>),
196 FeSpotLight(Box<FeSpotLight>),
197 FeTile(Box<FeTile>),
198 FeTurbulence(Box<FeTurbulence>),
199}
200
201#[rustfmt::skip]
202fn get_element_creators() -> &'static HashMap<&'static str, (ElementDataCreateFn, ElementCreateFlags)> {
203 use ElementCreateFlags::*;
204
205 ELEMENT_CREATORS.get_or_init(|| {
206 let creators_table: Vec<(&str, ElementDataCreateFn, ElementCreateFlags)> = vec![
208 ("a", create_link, Default),
210 ("circle", create_circle, Default),
218 ("clipPath", create_clip_path, Default),
219 ("defs", create_defs, Default),
222 ("ellipse", create_ellipse, Default),
224 ("feBlend", create_fe_blend, Default),
225 ("feColorMatrix", create_fe_color_matrix, Default),
226 ("feComponentTransfer", create_fe_component_transfer, Default),
227 ("feComposite", create_fe_composite, Default),
228 ("feConvolveMatrix", create_fe_convolve_matrix, Default),
229 ("feDiffuseLighting", create_fe_diffuse_lighting, Default),
230 ("feDisplacementMap", create_fe_displacement_map, Default),
231 ("feDistantLight", create_fe_distant_light, IgnoreClass),
232 ("feDropShadow", create_fe_drop_shadow, Default),
233 ("feFuncA", create_fe_func_a, IgnoreClass),
234 ("feFuncB", create_fe_func_b, IgnoreClass),
235 ("feFuncG", create_fe_func_g, IgnoreClass),
236 ("feFuncR", create_fe_func_r, IgnoreClass),
237 ("feFlood", create_fe_flood, Default),
238 ("feGaussianBlur", create_fe_gaussian_blur, Default),
239 ("feImage", create_fe_image, Default),
240 ("feMerge", create_fe_merge, Default),
241 ("feMergeNode", create_fe_merge_node, IgnoreClass),
242 ("feMorphology", create_fe_morphology, Default),
243 ("feOffset", create_fe_offset, Default),
244 ("fePointLight", create_fe_point_light, IgnoreClass),
245 ("feSpecularLighting", create_fe_specular_lighting, Default),
246 ("feSpotLight", create_fe_spot_light, IgnoreClass),
247 ("feTile", create_fe_tile, Default),
248 ("feTurbulence", create_fe_turbulence, Default),
249 ("filter", create_filter, Default),
250 ("g", create_group, Default),
258 ("image", create_image, Default),
262 ("line", create_line, Default),
263 ("linearGradient", create_linear_gradient, Default),
264 ("marker", create_marker, Default),
265 ("mask", create_mask, Default),
266 ("path", create_path, Default),
271 ("pattern", create_pattern, Default),
272 ("polygon", create_polygon, Default),
273 ("polyline", create_polyline, Default),
274 ("radialGradient", create_radial_gradient, Default),
275 ("rect", create_rect, Default),
276 ("stop", create_stop, Default),
279 ("style", create_style, IgnoreClass),
280 ("svg", create_svg, Default),
283 ("switch", create_switch, Default),
284 ("symbol", create_symbol, Default),
285 ("text", create_text, Default),
286 ("text2", create_text2, Default),
287 ("tref", create_tref, Default),
290 ("tspan", create_tspan, Default),
291 ("use", create_use, Default),
292 ];
295
296 creators_table.into_iter().map(|(n, c, f)| (n, (c, f))).collect()
297 })
298}
299
300impl Element {
301 pub fn new(session: &Session, name: &QualName, mut attributes: Attributes) -> Element {
306 let (create_fn, flags): (ElementDataCreateFn, ElementCreateFlags) = if name.ns == ns!(svg) {
307 match get_element_creators().get(name.local.as_ref()) {
308 Some(&(create_fn, flags)) => (create_fn, flags),
310
311 None => (create_non_rendering, ElementCreateFlags::Default),
315 }
316 } else {
317 (create_non_rendering, ElementCreateFlags::Default)
318 };
319
320 if flags == ElementCreateFlags::IgnoreClass {
321 attributes.clear_class();
322 };
323
324 let element_data = create_fn(session, &attributes);
325
326 let mut e = Self {
327 element_name: name.clone(),
328 attributes,
329 specified_values: Default::default(),
330 important_styles: Default::default(),
331 values: Default::default(),
332 required_extensions: Default::default(),
333 required_features: Default::default(),
334 system_language: Default::default(),
335 element_data,
336 };
337
338 e.set_conditional_processing_attributes(session);
339 e.set_presentation_attributes(session);
340
341 e
342 }
343
344 pub fn element_name(&self) -> &QualName {
345 &self.element_name
346 }
347
348 pub fn get_attributes(&self) -> &Attributes {
349 &self.attributes
350 }
351
352 pub fn get_id(&self) -> Option<&str> {
353 self.attributes.get_id()
354 }
355
356 pub fn get_class(&self) -> Option<&str> {
357 self.attributes.get_class()
358 }
359
360 pub fn inherit_xml_lang(&mut self, parent: Option<Node>) {
361 self.specified_values
362 .inherit_xml_lang(&mut self.values, parent);
363 }
364
365 pub fn get_specified_values(&self) -> &SpecifiedValues {
366 &self.specified_values
367 }
368
369 pub fn get_computed_values(&self) -> &ComputedValues {
370 &self.values
371 }
372
373 pub fn set_computed_values(&mut self, values: &ComputedValues) {
374 self.values = values.clone();
375 }
376
377 pub fn get_cond(&self, user_language: &UserLanguage) -> bool {
378 self.required_extensions
379 .as_ref()
380 .map(|v| v.eval())
381 .unwrap_or(true)
382 && self
383 .required_features
384 .as_ref()
385 .map(|v| v.eval())
386 .unwrap_or(true)
387 && self
388 .system_language
389 .as_ref()
390 .map(|v| v.eval(user_language))
391 .unwrap_or(true)
392 }
393
394 fn set_conditional_processing_attributes(&mut self, session: &Session) {
395 for (attr, value) in self.attributes.iter() {
396 match attr.expanded() {
397 expanded_name!("", "requiredExtensions") => {
398 self.required_extensions = Some(RequiredExtensions::from_attribute(value));
399 }
400
401 expanded_name!("", "requiredFeatures") => {
402 self.required_features = Some(RequiredFeatures::from_attribute(value));
403 }
404
405 expanded_name!("", "systemLanguage") => {
406 self.system_language = Some(SystemLanguage::from_attribute(value, session));
407 }
408
409 _ => {}
410 }
411 }
412 }
413
414 fn set_presentation_attributes(&mut self, session: &Session) {
416 self.specified_values
417 .parse_presentation_attributes(session, &self.attributes);
418 }
419
420 pub fn apply_style_declaration(&mut self, declaration: &Declaration, origin: Origin) {
422 self.specified_values.set_property_from_declaration(
423 declaration,
424 origin,
425 &mut self.important_styles,
426 );
427 }
428
429 pub fn set_style_attribute(&mut self, session: &Session) {
431 let style = self
432 .attributes
433 .iter()
434 .find(|(attr, _)| attr.expanded() == expanded_name!("", "style"))
435 .map(|(_, value)| value);
436
437 if let Some(style) = style {
438 self.specified_values.parse_style_declarations(
439 style,
440 Origin::Author,
441 &mut self.important_styles,
442 session,
443 );
444 }
445 }
446
447 #[rustfmt::skip]
448 pub fn as_filter_effect(&self) -> Option<&dyn FilterEffect> {
449 use ElementData::*;
450
451 match &self.element_data {
452 FeBlend(fe) => Some(&**fe),
453 FeColorMatrix(fe) => Some(&**fe),
454 FeComponentTransfer(fe) => Some(&**fe),
455 FeComposite(fe) => Some(&**fe),
456 FeConvolveMatrix(fe) => Some(&**fe),
457 FeDiffuseLighting(fe) => Some(&**fe),
458 FeDisplacementMap(fe) => Some(&**fe),
459 FeDropShadow(fe) => Some(&**fe),
460 FeFlood(fe) => Some(&**fe),
461 FeGaussianBlur(fe) => Some(&**fe),
462 FeImage(fe) => Some(&**fe),
463 FeMerge(fe) => Some(&**fe),
464 FeMorphology(fe) => Some(&**fe),
465 FeOffset(fe) => Some(&**fe),
466 FeSpecularLighting(fe) => Some(&**fe),
467 FeTile(fe) => Some(&**fe),
468 FeTurbulence(fe) => Some(&**fe),
469 _ => None,
470 }
471 }
472
473 pub fn is_accessed_by_reference(&self) -> bool {
477 use ElementData::*;
478
479 matches!(
480 self.element_data,
481 ClipPath(_)
482 | Filter(_)
483 | LinearGradient(_)
484 | Marker(_)
485 | Mask(_)
486 | Pattern(_)
487 | RadialGradient(_)
488 )
489 }
490
491 pub fn draw(
493 &self,
494 node: &Node,
495 acquired_nodes: &mut AcquiredNodes<'_>,
496 cascaded: &CascadedValues<'_>,
497 viewport: &Viewport,
498 draw_ctx: &mut DrawingCtx,
499 clipping: bool,
500 ) -> DrawResult {
501 let values = cascaded.get();
502 if values.is_displayed() {
503 self.element_data
504 .draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
505 } else {
506 Ok(viewport.empty_bbox())
507 }
508 }
509
510 pub fn layout(
512 &self,
513 node: &Node,
514 acquired_nodes: &mut AcquiredNodes<'_>,
515 cascaded: &CascadedValues<'_>,
516 viewport: &Viewport,
517 draw_ctx: &mut DrawingCtx,
518 clipping: bool,
519 ) -> Result<Option<Layer>, Box<InternalRenderingError>> {
520 let values = cascaded.get();
521 if values.is_displayed() {
522 self.element_data
523 .layout(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
524 } else {
525 Ok(None)
526 }
527 }
528}
529
530impl ElementData {
531 #[rustfmt::skip]
533 fn draw(
534 &self,
535 node: &Node,
536 acquired_nodes: &mut AcquiredNodes<'_>,
537 cascaded: &CascadedValues<'_>,
538 viewport: &Viewport,
539 draw_ctx: &mut DrawingCtx,
540 clipping: bool,
541 ) -> DrawResult {
542 use ElementData::*;
543
544 let data: &dyn ElementTrait = match self {
545 Circle(d) => &**d,
546 ClipPath(d) => &**d,
547 Ellipse(d) => &**d,
548 Filter(d) => &**d,
549 Group(d) => &**d,
550 Image(d) => &**d,
551 Line(d) => &**d,
552 LinearGradient(d) => &**d,
553 Link(d) => &**d,
554 Marker(d) => &**d,
555 Mask(d) => &**d,
556 NonRendering(d) => &**d,
557 Path(d) => &**d,
558 Pattern(d) => &**d,
559 Polygon(d) => &**d,
560 Polyline(d) => &**d,
561 RadialGradient(d) => &**d,
562 Rect(d) => &**d,
563 Stop(d) => &**d,
564 Style(d) => &**d,
565 Svg(d) => &**d,
566 Switch(d) => &**d,
567 Symbol(d) => &**d,
568 Text(d) => &**d,
569 Text2(d) => &**d,
570 TRef(d) => &**d,
571 TSpan(d) => &**d,
572 Use(d) => &**d,
573
574 FeBlend(d) => &**d,
575 FeColorMatrix(d) => &**d,
576 FeComponentTransfer(d) => &**d,
577 FeComposite(d) => &**d,
578 FeConvolveMatrix(d) => &**d,
579 FeDiffuseLighting(d) => &**d,
580 FeDisplacementMap(d) => &**d,
581 FeDistantLight(d) => &**d,
582 FeDropShadow(d) => &**d,
583 FeFlood(d) => &**d,
584 FeFuncA(d) => &**d,
585 FeFuncB(d) => &**d,
586 FeFuncG(d) => &**d,
587 FeFuncR(d) => &**d,
588 FeGaussianBlur(d) => &**d,
589 FeImage(d) => &**d,
590 FeMerge(d) => &**d,
591 FeMergeNode(d) => &**d,
592 FeMorphology(d) => &**d,
593 FeOffset(d) => &**d,
594 FePointLight(d) => &**d,
595 FeSpecularLighting(d) => &**d,
596 FeSpotLight(d) => &**d,
597 FeTile(d) => &**d,
598 FeTurbulence(d) => &**d,
599 };
600
601 data.draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
602 }
603
604 #[rustfmt::skip]
606 fn layout(
607 &self,
608 node: &Node,
609 acquired_nodes: &mut AcquiredNodes<'_>,
610 cascaded: &CascadedValues<'_>,
611 viewport: &Viewport,
612 draw_ctx: &mut DrawingCtx,
613 clipping: bool,
614 ) -> Result<Option<Layer>, Box<InternalRenderingError>> {
615 use ElementData::*;
616
617 let data: &dyn ElementTrait = match self {
618 Circle(d) => &**d,
619 ClipPath(d) => &**d,
620 Ellipse(d) => &**d,
621 Filter(d) => &**d,
622 Group(d) => &**d,
623 Image(d) => &**d,
624 Line(d) => &**d,
625 LinearGradient(d) => &**d,
626 Link(d) => &**d,
627 Marker(d) => &**d,
628 Mask(d) => &**d,
629 NonRendering(d) => &**d,
630 Path(d) => &**d,
631 Pattern(d) => &**d,
632 Polygon(d) => &**d,
633 Polyline(d) => &**d,
634 RadialGradient(d) => &**d,
635 Rect(d) => &**d,
636 Stop(d) => &**d,
637 Style(d) => &**d,
638 Svg(d) => &**d,
639 Switch(d) => &**d,
640 Symbol(d) => &**d,
641 Text(d) => &**d,
642 Text2(d) => &**d,
643 TRef(d) => &**d,
644 TSpan(d) => &**d,
645 Use(d) => &**d,
646
647 FeBlend(d) => &**d,
648 FeColorMatrix(d) => &**d,
649 FeComponentTransfer(d) => &**d,
650 FeComposite(d) => &**d,
651 FeConvolveMatrix(d) => &**d,
652 FeDiffuseLighting(d) => &**d,
653 FeDisplacementMap(d) => &**d,
654 FeDistantLight(d) => &**d,
655 FeDropShadow(d) => &**d,
656 FeFlood(d) => &**d,
657 FeFuncA(d) => &**d,
658 FeFuncB(d) => &**d,
659 FeFuncG(d) => &**d,
660 FeFuncR(d) => &**d,
661 FeGaussianBlur(d) => &**d,
662 FeImage(d) => &**d,
663 FeMerge(d) => &**d,
664 FeMergeNode(d) => &**d,
665 FeMorphology(d) => &**d,
666 FeOffset(d) => &**d,
667 FePointLight(d) => &**d,
668 FeSpecularLighting(d) => &**d,
669 FeSpotLight(d) => &**d,
670 FeTile(d) => &**d,
671 FeTurbulence(d) => &**d,
672 };
673
674 data.layout(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
675 }
676}
677
678macro_rules! e {
679 ($name:ident, $element_type:ident) => {
680 pub fn $name(session: &Session, attributes: &Attributes) -> ElementData {
681 let mut payload = Box::<$element_type>::default();
682 payload.set_attributes(attributes, session);
683
684 ElementData::$element_type(payload)
685 }
686 };
687}
688
689#[rustfmt::skip]
690mod creators {
691 use super::*;
692
693 e!(create_circle, Circle);
694 e!(create_clip_path, ClipPath);
695 e!(create_defs, NonRendering);
696 e!(create_ellipse, Ellipse);
697 e!(create_fe_blend, FeBlend);
698 e!(create_fe_color_matrix, FeColorMatrix);
699 e!(create_fe_component_transfer, FeComponentTransfer);
700 e!(create_fe_func_a, FeFuncA);
701 e!(create_fe_func_b, FeFuncB);
702 e!(create_fe_func_g, FeFuncG);
703 e!(create_fe_func_r, FeFuncR);
704 e!(create_fe_composite, FeComposite);
705 e!(create_fe_convolve_matrix, FeConvolveMatrix);
706 e!(create_fe_diffuse_lighting, FeDiffuseLighting);
707 e!(create_fe_displacement_map, FeDisplacementMap);
708 e!(create_fe_distant_light, FeDistantLight);
709 e!(create_fe_drop_shadow, FeDropShadow);
710 e!(create_fe_flood, FeFlood);
711 e!(create_fe_gaussian_blur, FeGaussianBlur);
712 e!(create_fe_image, FeImage);
713 e!(create_fe_merge, FeMerge);
714 e!(create_fe_merge_node, FeMergeNode);
715 e!(create_fe_morphology, FeMorphology);
716 e!(create_fe_offset, FeOffset);
717 e!(create_fe_point_light, FePointLight);
718 e!(create_fe_specular_lighting, FeSpecularLighting);
719 e!(create_fe_spot_light, FeSpotLight);
720 e!(create_fe_tile, FeTile);
721 e!(create_fe_turbulence, FeTurbulence);
722 e!(create_filter, Filter);
723 e!(create_group, Group);
724 e!(create_image, Image);
725 e!(create_line, Line);
726 e!(create_linear_gradient, LinearGradient);
727 e!(create_link, Link);
728 e!(create_marker, Marker);
729 e!(create_mask, Mask);
730 e!(create_non_rendering, NonRendering);
731 e!(create_path, Path);
732 e!(create_pattern, Pattern);
733 e!(create_polygon, Polygon);
734 e!(create_polyline, Polyline);
735 e!(create_radial_gradient, RadialGradient);
736 e!(create_rect, Rect);
737 e!(create_stop, Stop);
738 e!(create_style, Style);
739 e!(create_svg, Svg);
740 e!(create_switch, Switch);
741 e!(create_symbol, Symbol);
742 e!(create_text, Text);
743 e!(create_text2, Text2);
744 e!(create_tref, TRef);
745 e!(create_tspan, TSpan);
746 e!(create_use, Use);
747
748 }
761
762use creators::*;
763
764type ElementDataCreateFn = fn(session: &Session, attributes: &Attributes) -> ElementData;
765
766#[derive(Copy, Clone, PartialEq)]
767enum ElementCreateFlags {
768 Default,
769 IgnoreClass,
770}
771
772static ELEMENT_CREATORS: OnceLock<
773 HashMap<&'static str, (ElementDataCreateFn, ElementCreateFlags)>,
774> = OnceLock::new();