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