1use alloc::{collections::btree_map::BTreeMap, format, string::String, string::ToString, vec::Vec};
11use core::hash::Hash;
12
13use crate::{
14 corety::*,
15 css::*,
16 props::{basic::*, layout::*, property::*, style::*},
17};
18
19pub trait FormatAsRustCode {
21 fn format_as_rust_code(&self, tabs: usize) -> String;
22}
23
24pub trait GetHash {
26 fn get_hash(&self) -> u64;
27}
28
29impl<T: Hash> GetHash for T {
30 fn get_hash(&self) -> u64 {
31 use core::hash::Hasher;
32 let mut hasher = std::hash::DefaultHasher::new();
33 self.hash(&mut hasher);
34 hasher.finish()
35 }
36}
37
38impl<T: FormatAsRustCode + 'static> FormatAsRustCode for BoxOrStatic<T> {
42 fn format_as_rust_code(&self, tabs: usize) -> String {
43 self.as_ref().format_as_rust_code(tabs)
44 }
45}
46
47#[derive(Default)]
50pub struct VecContents {
51 pub strings: BTreeMap<u64, AzString>,
53 pub style_filters: BTreeMap<u64, StyleFilterVec>,
54 pub style_background_sizes: BTreeMap<u64, StyleBackgroundSizeVec>,
55 pub style_background_repeats: BTreeMap<u64, StyleBackgroundRepeatVec>,
56 pub style_background_contents: BTreeMap<u64, StyleBackgroundContentVec>,
57 pub style_background_positions: BTreeMap<u64, StyleBackgroundPositionVec>,
58 pub style_transforms: BTreeMap<u64, StyleTransformVec>,
59 pub font_families: BTreeMap<u64, StyleFontFamilyVec>,
60 pub linear_color_stops: BTreeMap<u64, NormalizedLinearColorStopVec>,
61 pub radial_color_stops: BTreeMap<u64, NormalizedRadialColorStopVec>,
62}
63
64impl VecContents {
65 pub fn format(&self, tabs: usize) -> String {
66 let mut result = String::new();
67 let t = " ".repeat(tabs);
68 let t2 = " ".repeat(tabs + 1);
69
70 for (key, item) in self.strings.iter() {
71 result.push_str(&format!(
72 "\r\n const STRING_{}: AzString = AzString::from_const_str(\"{}\");",
73 key,
74 item.as_str()
75 ));
76 }
77
78 for (key, item) in self.style_filters.iter() {
79 let val = item
80 .iter()
81 .map(|filter| format_style_filter(filter, tabs + 1))
82 .collect::<Vec<_>>()
83 .join(&format!(",\r\n{}", t));
84
85 result.push_str(&format!(
86 "\r\n const STYLE_FILTER_{}_ITEMS: &[StyleFilter] = &[\r\n{}{}\r\n{}];",
87 key, t2, val, t
88 ));
89 }
90
91 for (key, item) in self.style_background_sizes.iter() {
92 let val = item
93 .iter()
94 .map(format_style_background_size)
95 .collect::<Vec<_>>()
96 .join(&format!(",\r\n{}", t));
97
98 result.push_str(&format!(
99 "\r\n const STYLE_BACKGROUND_SIZE_{}_ITEMS: &[StyleBackgroundSize] = \
100 &[\r\n{}{}\r\n{}];",
101 key, t2, val, t
102 ));
103 }
104
105 for (key, item) in self.style_background_repeats.iter() {
106 let val = item
107 .iter()
108 .map(|bgr| bgr.format_as_rust_code(tabs + 1))
109 .collect::<Vec<_>>()
110 .join(&format!(",\r\n{}", t));
111
112 result.push_str(&format!(
113 "\r\n const STYLE_BACKGROUND_REPEAT_{}_ITEMS: &[StyleBackgroundRepeat] = \
114 &[\r\n{}{}\r\n{}];",
115 key, t2, val, t
116 ));
117 }
118
119 for (key, item) in self.style_background_contents.iter() {
120 let val = item
121 .iter()
122 .map(|bgc| format_style_background_content(bgc, tabs + 1))
123 .collect::<Vec<_>>()
124 .join(&format!(",\r\n{}", t));
125
126 result.push_str(&format!(
127 "\r\n const STYLE_BACKGROUND_CONTENT_{}_ITEMS: &[StyleBackgroundContent] = \
128 &[\r\n{}{}\r\n{}];",
129 key, t2, val, t
130 ));
131 }
132
133 for (key, item) in self.style_background_positions.iter() {
134 let val = item
135 .iter()
136 .map(|bgp| format_style_background_position(bgp, tabs))
137 .collect::<Vec<_>>()
138 .join(&format!(",\r\n{}", t));
139
140 result.push_str(&format!(
141 "\r\n const STYLE_BACKGROUND_POSITION_{}_ITEMS: &[StyleBackgroundPosition] = \
142 &[\r\n{}{}\r\n{}];",
143 key, t2, val, t
144 ));
145 }
146
147 for (key, item) in self.style_transforms.iter() {
148 let val = format_style_transforms(item.as_ref(), tabs + 1);
149
150 result.push_str(&format!(
151 "\r\n const STYLE_TRANSFORM_{}_ITEMS: &[StyleTransform] = &[\r\n{}{}\r\n{}];",
152 key, t2, val, t
153 ));
154 }
155
156 for (key, item) in self.font_families.iter() {
157 let val = format_font_ids(item.as_ref(), tabs + 1);
158
159 result.push_str(&format!(
160 "\r\n const STYLE_FONT_FAMILY_{}_ITEMS: &[StyleFontFamily] = &[\r\n{}{}\r\n{}];",
161 key, t2, val, t
162 ));
163 }
164
165 for (key, item) in self.linear_color_stops.iter() {
166 let val = format_linear_color_stops(item.as_ref(), 1);
167
168 result.push_str(&format!(
169 "\r\n const LINEAR_COLOR_STOP_{}_ITEMS: &[NormalizedLinearColorStop] = \
170 &[\r\n{}{}\r\n{}];",
171 key, t2, val, t
172 ));
173 }
174
175 for (key, item) in self.radial_color_stops.iter() {
176 let val = format_radial_color_stops(item.as_ref(), tabs);
177
178 result.push_str(&format!(
179 "\r\n const RADIAL_COLOR_STOP_{}_ITEMS: &[NormalizedRadialColorStop] = \
180 &[\r\n{}{}\r\n{}];",
181 key, t2, val, t
182 ));
183 }
184
185 result
186 }
187
188 pub fn insert_from_css_property(&mut self, prop: &CssProperty) {
190 match prop {
191 CssProperty::FontFamily(CssPropertyValue::Exact(v)) => {
192 for family in v.iter() {
193 match family {
194 StyleFontFamily::System(s) => {
195 let s = s.as_str();
198 let s = s.trim();
199 let s = s.trim_start_matches('\"');
200 let s = s.trim_end_matches('\"');
201 let s = s.trim_start_matches('\'');
202 let s = s.trim_end_matches('\'');
203
204 self.strings.insert(s.get_hash(), s.to_string().into());
205 }
206 StyleFontFamily::File(s) => {
207 let s = s.as_str();
208 let s = s.trim();
209 let s = s.trim_start_matches('\"');
210 let s = s.trim_end_matches('\"');
211 let s = s.trim_start_matches('\'');
212 let s = s.trim_end_matches('\'');
213
214 self.strings.insert(s.get_hash(), s.to_string().into());
215 }
216 _ => {}
217 }
218 }
219 self.font_families.insert(v.get_hash(), v.clone());
220 }
221 CssProperty::Transform(CssPropertyValue::Exact(v)) => {
222 self.style_transforms.insert(v.get_hash(), v.clone());
223 }
224 CssProperty::BackgroundRepeat(CssPropertyValue::Exact(v)) => {
225 self.style_background_repeats
226 .insert(v.get_hash(), v.clone());
227 }
228 CssProperty::BackgroundSize(CssPropertyValue::Exact(v)) => {
229 self.style_background_sizes.insert(v.get_hash(), v.clone());
230 }
231 CssProperty::BackgroundPosition(CssPropertyValue::Exact(v)) => {
232 self.style_background_positions
233 .insert(v.get_hash(), v.clone());
234 }
235 CssProperty::BackgroundContent(CssPropertyValue::Exact(ref v)) => {
236 for background in v.iter() {
237 match background {
238 StyleBackgroundContent::Image(id) => {
239 self.strings.insert(id.get_hash(), id.clone());
240 }
241 StyleBackgroundContent::LinearGradient(lg) => {
242 self.linear_color_stops
243 .insert(lg.stops.get_hash(), lg.stops.clone());
244 }
245 StyleBackgroundContent::RadialGradient(rg) => {
246 self.linear_color_stops
247 .insert(rg.stops.get_hash(), rg.stops.clone());
248 }
249 StyleBackgroundContent::ConicGradient(lg) => {
250 self.radial_color_stops
251 .insert(lg.stops.get_hash(), lg.stops.clone());
252 }
253 _ => {}
254 }
255 }
256 self.style_background_contents
257 .insert(v.get_hash(), v.clone());
258 }
259 CssProperty::Filter(CssPropertyValue::Exact(v)) => {
260 self.style_filters.insert(v.get_hash(), v.clone());
261 }
262 CssProperty::BackdropFilter(CssPropertyValue::Exact(v)) => {
263 self.style_filters.insert(v.get_hash(), v.clone());
264 }
265 _ => {}
266 }
267 }
268}
269
270pub fn format_pixel_value(p: &PixelValue) -> String {
274 let value = p.number.get();
275
276 let abs_val = libm::fabsf(value);
280 let sign: isize = if value < 0.0 { -1 } else { 1 };
281 let pre_comma = libm::floorf(abs_val) as isize * sign;
282 let post_comma = libm::roundf((abs_val - libm::floorf(abs_val)) * 100.0) as isize;
283
284 match p.metric {
285 SizeMetric::Pt => format!(
286 "PixelValue::const_pt_fractional({}, {})",
287 pre_comma, post_comma
288 ),
289 SizeMetric::Em => format!(
290 "PixelValue::const_em_fractional({}, {})",
291 pre_comma, post_comma
292 ),
293 other => format!(
294 "PixelValue::const_from_metric_fractional(SizeMetric::{:?}, {}, {})",
295 other, pre_comma, post_comma
296 ),
297 }
298}
299
300pub fn format_pixel_value_no_percent(p: &PixelValueNoPercent) -> String {
302 format!(
303 "PixelValueNoPercent {{ inner: {} }}",
304 format_pixel_value(&p.inner)
305 )
306}
307
308pub fn format_float_value(f: &FloatValue) -> String {
310 let value = f.get();
311 let abs_val = libm::fabsf(value);
312 let sign: isize = if value < 0.0 { -1 } else { 1 };
313 let pre_comma = libm::floorf(abs_val) as isize * sign;
314 let post_comma = libm::roundf((abs_val - libm::floorf(abs_val)) * 100.0) as isize;
315 format!(
316 "FloatValue::const_new_fractional({}, {})",
317 pre_comma, post_comma
318 )
319}
320
321pub fn format_percentage_value(f: &PercentageValue) -> String {
323 let value = f.normalized() * 100.0;
324 let abs_val = libm::fabsf(value);
325 let sign: isize = if value < 0.0 { -1 } else { 1 };
326 let pre_comma = libm::floorf(abs_val) as isize * sign;
327 let post_comma = libm::roundf((abs_val - libm::floorf(abs_val)) * 100.0) as isize;
328 format!(
329 "PercentageValue::const_new_fractional({}, {})",
330 pre_comma, post_comma
331 )
332}
333
334pub fn format_angle_value(f: &AngleValue) -> String {
336 let value = f.number.get();
337 let abs_val = libm::fabsf(value);
338 let sign: isize = if value < 0.0 { -1 } else { 1 };
339 let pre_comma = libm::floorf(abs_val) as isize * sign;
340 let post_comma = libm::roundf((abs_val - libm::floorf(abs_val)) * 100.0) as isize;
341 format!(
342 "AngleValue::const_from_metric_fractional(AngleMetric::{:?}, {}, {})",
343 f.metric, pre_comma, post_comma
344 )
345}
346
347pub fn format_color_value(c: &ColorU) -> String {
349 format!(
350 "ColorU {{ r: {}, g: {}, b: {}, a: {} }}",
351 c.r, c.g, c.b, c.a
352 )
353}
354
355fn format_grid_line(line: &GridLine, _tabs: usize) -> String {
356 match line {
357 GridLine::Auto => "GridLine::Auto".to_string(),
358 GridLine::Line(n) => format!("GridLine::Line({})", n),
359 GridLine::Named(named) => format!(
360 "GridLine::Named(NamedGridLine {{ grid_line_name: AzString::from_const_str({:?}), span_count: {} }})",
361 named.grid_line_name.as_ref(),
362 named.span_count,
363 ),
364 GridLine::Span(n) => format!("GridLine::Span({})", n),
365 }
366}
367
368fn format_color_or_system(c: &crate::props::basic::color::ColorOrSystem) -> String {
369 use crate::props::basic::color::{ColorOrSystem, SystemColorRef};
370 match c {
371 ColorOrSystem::Color(color) => format!("ColorOrSystem::Color({})", format_color_value(color)),
372 ColorOrSystem::System(system_ref) => {
373 let variant = match system_ref {
374 SystemColorRef::Text => "Text",
375 SystemColorRef::Background => "Background",
376 SystemColorRef::Accent => "Accent",
377 SystemColorRef::AccentText => "AccentText",
378 SystemColorRef::ButtonFace => "ButtonFace",
379 SystemColorRef::ButtonText => "ButtonText",
380 SystemColorRef::WindowBackground => "WindowBackground",
381 SystemColorRef::SelectionBackground => "SelectionBackground",
382 SystemColorRef::SelectionText => "SelectionText",
383 };
384 format!("ColorOrSystem::System(SystemColorRef::{})", variant)
385 }
386 }
387}
388
389macro_rules! impl_float_value_fmt {
392 ($struct_name:ident) => {
393 impl FormatAsRustCode for $struct_name {
394 fn format_as_rust_code(&self, _tabs: usize) -> String {
395 format!(
396 "{} {{ inner: {} }}",
397 stringify!($struct_name),
398 format_float_value(&self.inner)
399 )
400 }
401 }
402 };
403}
404
405impl_float_value_fmt!(LayoutFlexGrow);
406impl_float_value_fmt!(LayoutFlexShrink);
407
408macro_rules! impl_percentage_value_fmt {
409 ($struct_name:ident) => {
410 impl FormatAsRustCode for $struct_name {
411 fn format_as_rust_code(&self, _tabs: usize) -> String {
412 format!(
413 "{} {{ inner: {} }}",
414 stringify!($struct_name),
415 format_percentage_value(&self.inner)
416 )
417 }
418 }
419 };
420}
421
422impl_percentage_value_fmt!(StyleLineHeight);
423impl_percentage_value_fmt!(StyleOpacity);
424
425macro_rules! impl_pixel_value_fmt {
426 ($struct_name:ident) => {
427 impl FormatAsRustCode for $struct_name {
428 fn format_as_rust_code(&self, _tabs: usize) -> String {
429 format!(
430 "{} {{ inner: {} }}",
431 stringify!($struct_name),
432 format_pixel_value(&self.inner)
433 )
434 }
435 }
436 };
437}
438
439impl_pixel_value_fmt!(StyleTabSize);
440impl_pixel_value_fmt!(StyleBorderTopLeftRadius);
441impl_pixel_value_fmt!(StyleBorderBottomLeftRadius);
442impl_pixel_value_fmt!(StyleBorderTopRightRadius);
443impl_pixel_value_fmt!(StyleBorderBottomRightRadius);
444
445impl_pixel_value_fmt!(LayoutBorderTopWidth);
446impl_pixel_value_fmt!(LayoutBorderLeftWidth);
447impl_pixel_value_fmt!(LayoutBorderRightWidth);
448impl_pixel_value_fmt!(LayoutBorderBottomWidth);
449impl_pixel_value_fmt!(StyleLetterSpacing);
450impl_pixel_value_fmt!(StyleWordSpacing);
451impl_pixel_value_fmt!(StyleFontSize);
452
453impl_pixel_value_fmt!(LayoutMarginTop);
454impl_pixel_value_fmt!(LayoutMarginBottom);
455impl_pixel_value_fmt!(LayoutMarginRight);
456impl_pixel_value_fmt!(LayoutMarginLeft);
457
458impl_pixel_value_fmt!(LayoutPaddingTop);
459impl_pixel_value_fmt!(LayoutPaddingBottom);
460impl_pixel_value_fmt!(LayoutPaddingRight);
461impl_pixel_value_fmt!(LayoutPaddingLeft);
462impl_pixel_value_fmt!(LayoutPaddingInlineStart);
463impl_pixel_value_fmt!(LayoutPaddingInlineEnd);
464
465impl FormatAsRustCode for LayoutWidth {
466 fn format_as_rust_code(&self, _tabs: usize) -> String {
467 match self {
468 LayoutWidth::Auto => "LayoutWidth::Auto".to_string(),
469 LayoutWidth::Px(px) => format!("LayoutWidth::Px({})", format_pixel_value(px)),
470 LayoutWidth::MinContent => "LayoutWidth::MinContent".to_string(),
471 LayoutWidth::MaxContent => "LayoutWidth::MaxContent".to_string(),
472 LayoutWidth::FitContent(px) => format!("LayoutWidth::FitContent({})", format_pixel_value(px)),
473 LayoutWidth::Calc(items) => format!("LayoutWidth::Calc(/* {} items */)", items.len()),
474 }
475 }
476}
477
478impl FormatAsRustCode for LayoutHeight {
479 fn format_as_rust_code(&self, _tabs: usize) -> String {
480 match self {
481 LayoutHeight::Auto => "LayoutHeight::Auto".to_string(),
482 LayoutHeight::Px(px) => format!("LayoutHeight::Px({})", format_pixel_value(px)),
483 LayoutHeight::MinContent => "LayoutHeight::MinContent".to_string(),
484 LayoutHeight::MaxContent => "LayoutHeight::MaxContent".to_string(),
485 LayoutHeight::FitContent(px) => format!("LayoutHeight::FitContent({})", format_pixel_value(px)),
486 LayoutHeight::Calc(items) => format!("LayoutHeight::Calc(/* {} items */)", items.len()),
487 }
488 }
489}
490
491impl_pixel_value_fmt!(LayoutMinHeight);
492impl_pixel_value_fmt!(LayoutMinWidth);
493impl_pixel_value_fmt!(LayoutMaxWidth);
494impl_pixel_value_fmt!(LayoutMaxHeight);
495impl_pixel_value_fmt!(LayoutTop);
496impl_pixel_value_fmt!(LayoutInsetBottom);
497
498impl_pixel_value_fmt!(LayoutRight);
499impl_pixel_value_fmt!(LayoutLeft);
500
501impl_pixel_value_fmt!(LayoutColumnGap);
504impl_pixel_value_fmt!(LayoutRowGap);
505
506impl FormatAsRustCode for GridTemplate {
507 fn format_as_rust_code(&self, tabs: usize) -> String {
508 let tracks: Vec<String> = self
509 .tracks
510 .as_ref()
511 .iter()
512 .map(|t| t.format_as_rust_code(tabs))
513 .collect();
514 format!(
515 "GridTemplate {{ tracks: GridTrackSizingVec::from_vec(vec![{}]) }}",
516 tracks.join(", ")
517 )
518 }
519}
520
521impl FormatAsRustCode for GridPlacement {
522 fn format_as_rust_code(&self, tabs: usize) -> String {
523 format!(
524 "GridPlacement {{ grid_start: {}, grid_end: {} }}",
525 format_grid_line(&self.grid_start, tabs),
526 format_grid_line(&self.grid_end, tabs),
527 )
528 }
529}
530
531impl_color_value_fmt!(StyleTextColor);
532impl_color_value_fmt!(StyleBorderTopColor);
533impl_color_value_fmt!(StyleBorderLeftColor);
534impl_color_value_fmt!(StyleBorderRightColor);
535impl_color_value_fmt!(StyleBorderBottomColor);
536
537impl_enum_fmt!(
538 StyleMixBlendMode,
539 Normal,
540 Multiply,
541 Screen,
542 Overlay,
543 Darken,
544 Lighten,
545 ColorDodge,
546 ColorBurn,
547 HardLight,
548 SoftLight,
549 Difference,
550 Exclusion,
551 Hue,
552 Saturation,
553 Color,
554 Luminosity
555);
556
557impl_enum_fmt!(StyleHyphens, None, Manual, Auto);
558impl_enum_fmt!(StyleWordBreak, Normal, BreakAll, KeepAll, BreakWord);
559impl_enum_fmt!(StyleOverflowWrap, Normal, Anywhere, BreakWord);
560impl_enum_fmt!(StyleLineBreak, Auto, Loose, Normal, Strict, Anywhere);
561impl_enum_fmt!(StyleObjectFit, Fill, Contain, Cover, None, ScaleDown);
562
563impl FormatAsRustCode for StyleObjectPosition {
564 fn format_as_rust_code(&self, _tabs: usize) -> String {
565 format!("StyleObjectPosition {{ horizontal: {}, vertical: {} }}",
566 format_background_position_horizontal(&self.horizontal),
567 format_background_position_vertical(&self.vertical))
568 }
569}
570
571impl FormatAsRustCode for StyleAspectRatio {
572 fn format_as_rust_code(&self, _tabs: usize) -> String {
573 match self {
574 StyleAspectRatio::Auto => "StyleAspectRatio::Auto".to_string(),
575 StyleAspectRatio::Ratio(r) => format!("StyleAspectRatio::Ratio(AspectRatioValue {{ width: {}, height: {} }})", r.width, r.height),
576 }
577 }
578}
579
580impl_enum_fmt!(StyleTextOrientation, Mixed, Upright, Sideways);
581impl_enum_fmt!(StyleTextAlignLast, Auto, Start, End, Left, Right, Center, Justify);
582
583impl_enum_fmt!(StyleDirection, Ltr, Rtl);
584
585impl_enum_fmt!(StyleWhiteSpace, Normal, Pre, Nowrap, PreWrap, PreLine, BreakSpaces);
586
587impl_enum_fmt!(StyleVisibility, Visible, Hidden, Collapse);
588
589impl_enum_fmt!(LayoutWritingMode, HorizontalTb, VerticalRl, VerticalLr);
590
591impl_enum_fmt!(LayoutClear, None, Left, Right, Both);
592
593impl_enum_fmt!(
594 StyleCursor,
595 Alias,
596 AllScroll,
597 Cell,
598 ColResize,
599 ContextMenu,
600 Copy,
601 Crosshair,
602 Default,
603 EResize,
604 EwResize,
605 Grab,
606 Grabbing,
607 Help,
608 Move,
609 NResize,
610 NsResize,
611 NeswResize,
612 NwseResize,
613 Pointer,
614 Progress,
615 RowResize,
616 SResize,
617 SeResize,
618 Text,
619 Unset,
620 VerticalText,
621 WResize,
622 Wait,
623 ZoomIn,
624 ZoomOut
625);
626
627impl_enum_fmt!(
628 BorderStyle,
629 None,
630 Solid,
631 Double,
632 Dotted,
633 Dashed,
634 Hidden,
635 Groove,
636 Ridge,
637 Inset,
638 Outset
639);
640
641impl_enum_fmt!(
642 StyleBackgroundRepeat,
643 NoRepeat,
644 PatternRepeat,
645 RepeatX,
646 RepeatY
647);
648
649impl_enum_fmt!(
650 LayoutDisplay,
651 None,
652 Block,
653 Inline,
654 InlineBlock,
655 Flex,
656 InlineFlex,
657 Table,
658 InlineTable,
659 TableRowGroup,
660 TableHeaderGroup,
661 TableFooterGroup,
662 TableRow,
663 TableColumnGroup,
664 TableColumn,
665 TableCell,
666 TableCaption,
667 ListItem,
668 RunIn,
669 Marker,
670 Grid,
671 InlineGrid,
672 FlowRoot,
673 Contents
674);
675
676impl_enum_fmt!(LayoutFloat, Left, Right, None);
677
678impl_enum_fmt!(LayoutBoxSizing, ContentBox, BorderBox);
679
680impl_enum_fmt!(LayoutFlexDirection, Row, RowReverse, Column, ColumnReverse);
681
682impl_enum_fmt!(LayoutFlexWrap, Wrap, NoWrap, WrapReverse);
683
684impl_enum_fmt!(
685 LayoutJustifyContent,
686 Start,
687 End,
688 FlexStart,
689 FlexEnd,
690 Center,
691 SpaceBetween,
692 SpaceAround,
693 SpaceEvenly
694);
695
696impl_enum_fmt!(LayoutAlignItems, Stretch, Center, Start, End, Baseline);
697
698impl_enum_fmt!(
699 LayoutAlignContent,
700 Start,
701 End,
702 Stretch,
703 Center,
704 SpaceBetween,
705 SpaceAround
706);
707
708impl_enum_fmt!(Shape, Circle, Ellipse);
709
710impl_enum_fmt!(LayoutOverflow, Auto, Scroll, Visible, Hidden, Clip);
711
712impl_enum_fmt!(StyleTextAlign, Center, Left, Right, Justify, Start, End);
713
714impl_enum_fmt!(StyleUserSelect, Auto, Text, None, All);
715
716impl_enum_fmt!(StyleTextDecoration, None, Underline, Overline, LineThrough);
717
718impl_enum_fmt!(
719 DirectionCorner,
720 Right,
721 Left,
722 Top,
723 Bottom,
724 TopRight,
725 TopLeft,
726 BottomRight,
727 BottomLeft
728);
729
730impl_enum_fmt!(ExtendMode, Clamp, Repeat);
731
732impl_enum_fmt!(StyleBackfaceVisibility, Visible, Hidden);
733
734impl_enum_fmt!(StyleUnicodeBidi, Normal, Embed, Isolate, BidiOverride, IsolateOverride, Plaintext);
735impl_enum_fmt!(StyleTextBoxTrim, None, TrimStart, TrimEnd, TrimBoth);
736impl_enum_fmt!(StyleTextBoxEdge, Auto, TextEdge, CapHeight, ExHeight);
737impl_enum_fmt!(StyleDominantBaseline, Auto, TextBottom, Alphabetic, Ideographic, Middle, Central, Mathematical, Hanging, TextTop);
738impl_enum_fmt!(StyleAlignmentBaseline, Baseline, TextBottom, Alphabetic, Ideographic, Middle, Central, Mathematical, TextTop);
739impl_enum_fmt!(StyleInitialLetterAlign, Auto, Alphabetic, Hanging, Ideographic);
740impl_enum_fmt!(StyleInitialLetterWrap, None, First, All, Grid);
741impl_enum_fmt!(StyleScrollbarGutter, Auto, Stable, StableBothEdges);
742
743impl FormatAsRustCode for StyleOverflowClipMargin {
744 fn format_as_rust_code(&self, tabs: usize) -> String {
745 format!("StyleOverflowClipMargin {{ inner: {} }}", self.inner.format_as_rust_code(tabs))
746 }
747}
748
749impl FormatAsRustCode for StyleClipRect {
750 fn format_as_rust_code(&self, _tabs: usize) -> String {
751 fn fmt_edge(o: &OptionF32) -> String {
752 match o {
753 OptionF32::None => String::from("OptionF32::None"),
754 OptionF32::Some(v) => format!("OptionF32::Some({:?})", v),
755 }
756 }
757 format!(
758 "StyleClipRect {{ top: {}, right: {}, bottom: {}, left: {} }}",
759 fmt_edge(&self.top),
760 fmt_edge(&self.right),
761 fmt_edge(&self.bottom),
762 fmt_edge(&self.left),
763 )
764 }
765}
766
767fn format_style_background_size(c: &StyleBackgroundSize) -> String {
770 match c {
771 StyleBackgroundSize::Contain => String::from("StyleBackgroundSize::Contain"),
772 StyleBackgroundSize::Cover => String::from("StyleBackgroundSize::Cover"),
773 StyleBackgroundSize::ExactSize(size) => format!(
774 "StyleBackgroundSize::ExactSize(PixelValueSize {{ width: {}, height: {} }})",
775 format_pixel_value(&size.width),
776 format_pixel_value(&size.height)
777 ),
778 }
779}
780
781pub fn format_scrollbar_info(s: &ScrollbarInfo, tabs: usize) -> String {
785 let t = String::from(" ").repeat(tabs);
786 let t1 = String::from(" ").repeat(tabs + 1);
787 format!(
788 "ScrollbarInfo {{\r\n{}width: {},\r\n{}padding_left: {},\r\n{}padding_right: \
789 {},\r\n{}track: {},\r\n{}thumb: {},\r\n{}button: {},\r\n{}button: {},\r\n{}resizer: \
790 {},\r\n{}}}",
791 t1,
792 s.width.format_as_rust_code(tabs + 1),
793 t1,
794 s.padding_left.format_as_rust_code(tabs + 1),
795 t1,
796 s.padding_right.format_as_rust_code(tabs + 1),
797 t1,
798 format_style_background_content(&s.track, tabs + 1),
799 t1,
800 format_style_background_content(&s.thumb, tabs + 1),
801 t1,
802 format_style_background_content(&s.button, tabs + 1),
803 t1,
804 format_style_background_content(&s.corner, tabs + 1),
805 t1,
806 format_style_background_content(&s.resizer, tabs + 1),
807 t
808 )
809}
810
811fn format_style_background_content(content: &StyleBackgroundContent, tabs: usize) -> String {
814 match content {
815 StyleBackgroundContent::LinearGradient(l) => format!(
816 "StyleBackgroundContent::LinearGradient({})",
817 format_linear_gradient(l, tabs)
818 ),
819 StyleBackgroundContent::RadialGradient(r) => format!(
820 "StyleBackgroundContent::RadialGradient({})",
821 format_radial_gradient(r, tabs)
822 ),
823 StyleBackgroundContent::ConicGradient(r) => format!(
824 "StyleBackgroundContent::ConicGradient({})",
825 format_conic_gradient(r, tabs)
826 ),
827 StyleBackgroundContent::Image(id) => format!("StyleBackgroundContent::Image({:?})", id),
828 StyleBackgroundContent::Color(c) => {
829 format!("StyleBackgroundContent::Color({})", format_color_value(c))
830 }
831 }
832}
833
834fn format_direction(d: &Direction, tabs: usize) -> String {
835 match d {
836 Direction::Angle(fv) => format!("Direction::Angle({})", format_angle_value(fv)),
837 Direction::FromTo(DirectionCorners { dir_from, dir_to }) => format!(
838 "Direction::FromTo(DirectionCorners {{ dir_from: {}, dir_to: {} }})",
839 dir_from.format_as_rust_code(tabs + 1),
840 dir_to.format_as_rust_code(tabs + 1)
841 ),
842 }
843}
844
845fn format_linear_gradient(l: &LinearGradient, tabs: usize) -> String {
846 let t = String::from(" ").repeat(tabs);
847 let t1 = String::from(" ").repeat(tabs + 1);
848 format!(
849 "LinearGradient {{\r\n{}direction: {},\r\n{}extend_mode: {},\r\n{}stops: \
850 NormalizedLinearColorStopVec::from_const_slice(LINEAR_COLOR_STOP_{}_ITEMS),\r\n{}}}",
851 t1,
852 format_direction(&l.direction, tabs + 1),
853 t1,
854 l.extend_mode.format_as_rust_code(tabs + 1),
855 t1,
856 l.stops.get_hash(),
857 t,
858 )
859}
860
861fn format_conic_gradient(r: &ConicGradient, tabs: usize) -> String {
862 let t = String::from(" ").repeat(tabs);
863 let t1 = String::from(" ").repeat(tabs + 1);
864
865 format!(
866 "ConicGradient {{\r\n{}extend_mode: {},\r\n{}center: {},\r\n{}angle: {},\r\n{}stops: \
867 NormalizedRadialColorStopVec::from_const_slice(RADIAL_COLOR_STOP_{}_ITEMS),\r\n{}}}",
868 t1,
869 r.extend_mode.format_as_rust_code(tabs + 1),
870 t1,
871 format_style_background_position(&r.center, tabs + 1),
872 t1,
873 format_angle_value(&r.angle),
874 t1,
875 r.stops.get_hash(),
876 t,
877 )
878}
879
880fn format_radial_gradient(r: &RadialGradient, tabs: usize) -> String {
881 let t = String::from(" ").repeat(tabs);
882 let t1 = String::from(" ").repeat(tabs + 1);
883 format!(
884 "RadialGradient {{\r\n{}shape: {},\r\n{}extend_mode: {},\r\n{}position: {},\r\n{}size: \
885 RadialGradientSize::{:?},\r\n{}stops: \
886 NormalizedLinearColorStopVec::from_const_slice(LINEAR_COLOR_STOP_{}_ITEMS),\r\n{}}}",
887 t1,
888 r.shape.format_as_rust_code(tabs + 1),
889 t1,
890 r.extend_mode.format_as_rust_code(tabs + 1),
891 t1,
892 format_style_background_position(&r.position, tabs + 1),
893 t1,
894 r.size,
895 t1,
896 r.stops.get_hash(),
897 t,
898 )
899}
900
901fn format_linear_color_stops(stops: &[NormalizedLinearColorStop], tabs: usize) -> String {
902 let t = String::from(" ").repeat(tabs);
903 stops
904 .iter()
905 .map(format_linear_color_stop)
906 .collect::<Vec<_>>()
907 .join(&format!(",\r\n{}", t))
908}
909
910fn format_linear_color_stop(g: &NormalizedLinearColorStop) -> String {
911 format!(
912 "NormalizedLinearColorStop {{ offset: {}, color: {} }}",
913 format_percentage_value(&g.offset),
914 format_color_or_system(&g.color),
915 )
916}
917
918fn format_radial_color_stops(stops: &[NormalizedRadialColorStop], tabs: usize) -> String {
919 let t = String::from(" ").repeat(tabs);
920 stops
921 .iter()
922 .map(format_radial_color_stop)
923 .collect::<Vec<_>>()
924 .join(&format!(",\r\n{}", t))
925}
926
927fn format_radial_color_stop(g: &NormalizedRadialColorStop) -> String {
928 format!(
929 "RadialColorStop {{ angle: {}, color: {} }}",
930 format_angle_value(&g.angle),
931 format_color_or_system(&g.color),
932 )
933}
934
935fn format_style_filter(st: &StyleFilter, tabs: usize) -> String {
936 match st {
937 StyleFilter::Blend(mb) => format!("StyleFilter::Blend({})", mb.format_as_rust_code(tabs)),
938 StyleFilter::Flood(c) => format!("StyleFilter::Flood({})", format_color_value(c)),
939 StyleFilter::Blur(m) => format!(
940 "StyleFilter::Blur(StyleBlur {{ width: {}, height: {} }})",
941 format_pixel_value(&m.width),
942 format_pixel_value(&m.height)
943 ),
944 StyleFilter::Opacity(pct) => {
945 format!("StyleFilter::Opacity({})", format_percentage_value(pct))
946 }
947 StyleFilter::ColorMatrix(cm) => format!(
948 "StyleFilter::ColorMatrix(StyleColorMatrix {{ m0: {}, m1: {}, m2: {}, m3: {}, m4: {}, \
949 m5: {}, m6: {}, m7: {}, m8: {}, m9: {}, m10: {}, m11: {}, m12: {}, m13: {}, m14: {}, \
950 m15: {}, m16: {}, m17: {}, m18: {}, m19: {} }})",
951 format_float_value(&cm.m0),
952 format_float_value(&cm.m1),
953 format_float_value(&cm.m2),
954 format_float_value(&cm.m3),
955 format_float_value(&cm.m4),
956 format_float_value(&cm.m5),
957 format_float_value(&cm.m6),
958 format_float_value(&cm.m7),
959 format_float_value(&cm.m8),
960 format_float_value(&cm.m9),
961 format_float_value(&cm.m10),
962 format_float_value(&cm.m11),
963 format_float_value(&cm.m12),
964 format_float_value(&cm.m13),
965 format_float_value(&cm.m14),
966 format_float_value(&cm.m15),
967 format_float_value(&cm.m16),
968 format_float_value(&cm.m17),
969 format_float_value(&cm.m18),
970 format_float_value(&cm.m19)
971 ),
972 StyleFilter::DropShadow(m) => {
973 format!("StyleFilter::DropShadow({})", m.format_as_rust_code(tabs))
974 }
975 StyleFilter::ComponentTransfer => "StyleFilter::ComponentTransfer".to_string(),
976 StyleFilter::Offset(o) => format!(
977 "StyleFilter::Offset(StyleFilterOffset {{ x: {}, y: {} }})",
978 format_pixel_value(&o.x),
979 format_pixel_value(&o.y)
980 ),
981 StyleFilter::Composite(StyleCompositeFilter::Over) => {
982 "StyleFilter::Composite(StyleCompositeFilter::Over)".to_string()
983 }
984 StyleFilter::Composite(StyleCompositeFilter::In) => {
985 "StyleFilter::Composite(StyleCompositeFilter::In)".to_string()
986 }
987 StyleFilter::Composite(StyleCompositeFilter::Atop) => {
988 "StyleFilter::Composite(StyleCompositeFilter::Atop)".to_string()
989 }
990 StyleFilter::Composite(StyleCompositeFilter::Out) => {
991 "StyleFilter::Composite(StyleCompositeFilter::Out)".to_string()
992 }
993 StyleFilter::Composite(StyleCompositeFilter::Xor) => {
994 "StyleFilter::Composite(StyleCompositeFilter::Xor)".to_string()
995 }
996 StyleFilter::Composite(StyleCompositeFilter::Lighter) => {
997 "StyleFilter::Composite(StyleCompositeFilter::Lighter)".to_string()
998 }
999 StyleFilter::Composite(StyleCompositeFilter::Arithmetic(fv)) => format!(
1000 "StyleFilter::Composite(StyleCompositeFilter::Arithmetic(ArithmeticCoefficients {{ \
1001 k1: {}, k2: {}, k3: {}, k4: {} }}))",
1002 format_float_value(&fv.k1),
1003 format_float_value(&fv.k2),
1004 format_float_value(&fv.k3),
1005 format_float_value(&fv.k4)
1006 ),
1007 StyleFilter::Brightness(v) => format!("StyleFilter::Brightness({})", format_percentage_value(v)),
1008 StyleFilter::Contrast(v) => format!("StyleFilter::Contrast({})", format_percentage_value(v)),
1009 StyleFilter::Grayscale(v) => format!("StyleFilter::Grayscale({})", format_percentage_value(v)),
1010 StyleFilter::HueRotate(a) => format!("StyleFilter::HueRotate({})", format_angle_value(a)),
1011 StyleFilter::Invert(v) => format!("StyleFilter::Invert({})", format_percentage_value(v)),
1012 StyleFilter::Saturate(v) => format!("StyleFilter::Saturate({})", format_percentage_value(v)),
1013 StyleFilter::Sepia(v) => format!("StyleFilter::Sepia({})", format_percentage_value(v)),
1014 }
1015}
1016
1017fn format_style_transforms(stops: &[StyleTransform], tabs: usize) -> String {
1018 let t = String::from(" ").repeat(tabs);
1019 stops
1020 .iter()
1021 .map(|s| format_style_transform(s, tabs))
1022 .collect::<Vec<_>>()
1023 .join(&format!(",\r\n{}", t))
1024}
1025
1026fn format_style_transform(st: &StyleTransform, tabs: usize) -> String {
1027 let tabs_minus_one = String::from(" ").repeat(tabs);
1028 let tabs = String::from(" ").repeat(tabs + 1);
1029 match st {
1030 StyleTransform::Matrix(m) => format!(
1031 "StyleTransform::Matrix(StyleTransformMatrix2D {{ a: {}, b: {}, c: {}, d: {}, tx: {}, \
1032 ty: {} }})",
1033 format_float_value(&m.a),
1034 format_float_value(&m.b),
1035 format_float_value(&m.c),
1036 format_float_value(&m.d),
1037 format_float_value(&m.tx),
1038 format_float_value(&m.ty)
1039 ),
1040 StyleTransform::Matrix3D(m) => format!(
1041 "StyleTransform::Matrix3D(StyleTransformMatrix3D {{\r\n{tabs}m11: {},\r\n{tabs}m12: \
1042 {},\r\n{tabs}m13: {},\r\n{tabs}m14: {},\r\n{tabs}m21: {},\r\n{tabs}m22: \
1043 {},\r\n{tabs}m23: {},\r\n{tabs}m24: {},\r\n{tabs}m31: {},\r\n{tabs}m32: \
1044 {},\r\n{tabs}m33: {},\r\n{tabs}m34: {},\r\n{tabs}m41: {},\r\n{tabs}m42: \
1045 {},\r\n{tabs}m43: {},\r\n{tabs}m44: {}\r\n{tabs_minus_one}}})",
1046 format_float_value(&m.m11),
1047 format_float_value(&m.m12),
1048 format_float_value(&m.m13),
1049 format_float_value(&m.m14),
1050 format_float_value(&m.m21),
1051 format_float_value(&m.m22),
1052 format_float_value(&m.m23),
1053 format_float_value(&m.m24),
1054 format_float_value(&m.m31),
1055 format_float_value(&m.m32),
1056 format_float_value(&m.m33),
1057 format_float_value(&m.m34),
1058 format_float_value(&m.m41),
1059 format_float_value(&m.m42),
1060 format_float_value(&m.m43),
1061 format_float_value(&m.m44),
1062 tabs = tabs,
1063 tabs_minus_one = tabs_minus_one,
1064 ),
1065 StyleTransform::Translate(t) => format!(
1066 "StyleTransform::Translate(StyleTransformTranslate2D {{ x: {}, y: {} }})",
1067 format_pixel_value(&t.x),
1068 format_pixel_value(&t.y)
1069 ),
1070 StyleTransform::Translate3D(t) => format!(
1071 "StyleTransform::Translate3D(StyleTransformTranslate3D {{ x: {}, y: {}, z: {} }})",
1072 format_pixel_value(&t.x),
1073 format_pixel_value(&t.y),
1074 format_pixel_value(&t.z)
1075 ),
1076 StyleTransform::TranslateX(x) => {
1077 format!("StyleTransform::TranslateX({})", format_pixel_value(x))
1078 }
1079 StyleTransform::TranslateY(y) => {
1080 format!("StyleTransform::TranslateY({})", format_pixel_value(y))
1081 }
1082 StyleTransform::TranslateZ(z) => {
1083 format!("StyleTransform::TranslateZ({})", format_pixel_value(z))
1084 }
1085 StyleTransform::Rotate(r) => format!("StyleTransform::Rotate({})", format_angle_value(r)),
1086 StyleTransform::Rotate3D(r) => format!(
1087 "StyleTransform::Rotate3D(StyleTransformRotate3D {{ {}, {}, {}, {} }})",
1088 format_float_value(&r.x),
1089 format_float_value(&r.y),
1090 format_float_value(&r.z),
1091 format_angle_value(&r.angle)
1092 ),
1093 StyleTransform::RotateX(x) => {
1094 format!("StyleTransform::RotateX({})", format_angle_value(x))
1095 }
1096 StyleTransform::RotateY(y) => {
1097 format!("StyleTransform::RotateY({})", format_angle_value(y))
1098 }
1099 StyleTransform::RotateZ(z) => {
1100 format!("StyleTransform::RotateZ({})", format_angle_value(z))
1101 }
1102 StyleTransform::Scale(s) => format!(
1103 "StyleTransform::Scale(StyleTransformScale2D {{ x: {}, y: {} }})",
1104 format_float_value(&s.x),
1105 format_float_value(&s.y)
1106 ),
1107 StyleTransform::Scale3D(s) => format!(
1108 "StyleTransform::Scale3D(StyleTransformScale3D {{ x: {}, y: {}, z: {} }})",
1109 format_float_value(&s.x),
1110 format_float_value(&s.y),
1111 format_float_value(&s.z)
1112 ),
1113 StyleTransform::ScaleX(x) => {
1114 format!("StyleTransform::ScaleX({})", format_percentage_value(x))
1115 }
1116 StyleTransform::ScaleY(y) => {
1117 format!("StyleTransform::ScaleY({})", format_percentage_value(y))
1118 }
1119 StyleTransform::ScaleZ(z) => {
1120 format!("StyleTransform::ScaleZ({})", format_percentage_value(z))
1121 }
1122 StyleTransform::Skew(sk) => format!(
1123 "StyleTransform::Skew(StyleTransformSkew2D {{ x: {}, y: {} }})",
1124 format_angle_value(&sk.x),
1125 format_angle_value(&sk.y)
1126 ),
1127 StyleTransform::SkewX(x) => {
1128 format!("StyleTransform::SkewX({})", format_angle_value(x))
1129 }
1130 StyleTransform::SkewY(y) => {
1131 format!("StyleTransform::SkewY({})", format_angle_value(y))
1132 }
1133 StyleTransform::Perspective(dist) => {
1134 format!("StyleTransform::Perspective({})", format_pixel_value(dist))
1135 }
1136 }
1137}
1138
1139fn format_font_ids(font_ids: &[StyleFontFamily], tabs: usize) -> String {
1140 let t = String::from(" ").repeat(tabs);
1141 font_ids
1142 .iter()
1143 .map(|s| s.format_as_rust_code(tabs + 1).to_string())
1144 .collect::<Vec<_>>()
1145 .join(&format!(",\r\n{}", t))
1146}
1147
1148fn format_style_background_position(b: &StyleBackgroundPosition, tabs: usize) -> String {
1149 let t = String::from(" ").repeat(tabs);
1150 let t1 = String::from(" ").repeat(tabs + 1);
1151 format!(
1152 "StyleBackgroundPosition {{\r\n{}horizontal: {},\r\n{}vertical: {},\r\n{}}}",
1153 t1,
1154 format_background_position_horizontal(&b.horizontal),
1155 t1,
1156 format_background_position_vertical(&b.vertical),
1157 t
1158 )
1159}
1160
1161fn format_background_position_horizontal(b: &BackgroundPositionHorizontal) -> String {
1162 match b {
1163 BackgroundPositionHorizontal::Left => "BackgroundPositionHorizontal::Left".to_string(),
1164 BackgroundPositionHorizontal::Center => "BackgroundPositionHorizontal::Center".to_string(),
1165 BackgroundPositionHorizontal::Right => "BackgroundPositionHorizontal::Right".to_string(),
1166 BackgroundPositionHorizontal::Exact(p) => format!(
1167 "BackgroundPositionHorizontal::Exact({})",
1168 format_pixel_value(p)
1169 ),
1170 }
1171}
1172
1173fn format_background_position_vertical(b: &BackgroundPositionVertical) -> String {
1174 match b {
1175 BackgroundPositionVertical::Top => "BackgroundPositionVertical::Top".to_string(),
1176 BackgroundPositionVertical::Center => "BackgroundPositionVertical::Center".to_string(),
1177 BackgroundPositionVertical::Bottom => "BackgroundPositionVertical::Bottom".to_string(),
1178 BackgroundPositionVertical::Exact(p) => format!(
1179 "BackgroundPositionVertical::Exact({})",
1180 format_pixel_value(p)
1181 ),
1182 }
1183}
1184
1185