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