1use crate::computed_value_flags::ComputedValueFlags;
9use crate::dom::TElement;
10use crate::properties::longhands::display::computed_value::T as Display;
11use crate::properties::longhands::float::computed_value::T as Float;
12use crate::properties::longhands::position::computed_value::T as Position;
13#[cfg(feature = "gecko")]
14use crate::properties::longhands::{
15 contain::computed_value::T as Contain, container_type::computed_value::T as ContainerType,
16 content_visibility::computed_value::T as ContentVisibility,
17 overflow_x::computed_value::T as Overflow,
18};
19use crate::properties::{self, ComputedValues, StyleBuilder};
20
21#[cfg(feature = "gecko")]
22use selectors::parser::PseudoElement;
23
24pub struct StyleAdjuster<'a, 'b: 'a> {
38 style: &'a mut StyleBuilder<'b>,
39}
40
41#[cfg(feature = "gecko")]
42fn is_topmost_svg_svg_element<E>(e: E) -> bool
43where
44 E: TElement,
45{
46 debug_assert!(e.is_svg_element());
47 if e.local_name() != &*atom!("svg") {
48 return false;
49 }
50
51 let parent = match e.traversal_parent() {
52 Some(n) => n,
53 None => return true,
54 };
55
56 if !parent.is_svg_element() {
57 return true;
58 }
59
60 parent.local_name() == &*atom!("foreignObject")
61}
62
63#[cfg(feature = "gecko")]
65fn is_effective_display_none_for_display_contents<E>(element: E) -> bool
66where
67 E: TElement,
68{
69 use crate::Atom;
70
71 const SPECIAL_HTML_ELEMENTS: [Atom; 16] = [
72 atom!("br"),
73 atom!("wbr"),
74 atom!("meter"),
75 atom!("progress"),
76 atom!("canvas"),
77 atom!("embed"),
78 atom!("object"),
79 atom!("audio"),
80 atom!("iframe"),
81 atom!("img"),
82 atom!("video"),
83 atom!("frame"),
84 atom!("frameset"),
85 atom!("input"),
86 atom!("textarea"),
87 atom!("select"),
88 ];
89
90 const SPECIAL_SVG_ELEMENTS: [Atom; 6] = [
96 atom!("svg"),
97 atom!("a"),
98 atom!("g"),
99 atom!("use"),
100 atom!("tspan"),
101 atom!("textPath"),
102 ];
103
104 if element.is_html_element() {
106 let local_name = element.local_name();
107 return SPECIAL_HTML_ELEMENTS
108 .iter()
109 .any(|name| &**name == local_name);
110 }
111
112 if element.is_svg_element() {
114 if is_topmost_svg_svg_element(element) {
115 return true;
116 }
117 let local_name = element.local_name();
118 return !SPECIAL_SVG_ELEMENTS
119 .iter()
120 .any(|name| &**name == local_name);
121 }
122
123 if element.is_mathml_element() {
125 return true;
126 }
127
128 false
129}
130
131impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
132 #[inline]
134 pub fn new(style: &'a mut StyleBuilder<'b>) -> Self {
135 StyleAdjuster { style }
136 }
137
138 fn adjust_for_top_layer(&mut self) {
144 if !self.style.in_top_layer() {
145 return;
146 }
147 if !self.style.is_absolutely_positioned() {
148 self.style.mutate_box().set_position(Position::Absolute);
149 }
150 if self.style.get_box().clone_display().is_contents() {
151 self.style.mutate_box().set_display(Display::Block);
152 }
153 }
154
155 #[cfg(feature = "gecko")]
162 fn adjust_for_webkit_line_clamp(&mut self) {
163 use crate::properties::longhands::_moz_box_orient::computed_value::T as BoxOrient;
164 use crate::values::specified::box_::{DisplayInside, DisplayOutside};
165 let box_style = self.style.get_box();
166 if box_style.clone__webkit_line_clamp().is_none() {
167 return;
168 }
169 let disp = box_style.clone_display();
170 if disp.inside() != DisplayInside::WebkitBox {
171 return;
172 }
173 if self.style.get_xul().clone__moz_box_orient() != BoxOrient::Vertical {
174 return;
175 }
176 let new_display = if disp.outside() == DisplayOutside::Block {
177 Display::FlowRoot
178 } else {
179 debug_assert_eq!(disp.outside(), DisplayOutside::Inline);
180 Display::InlineBlock
181 };
182 self.style
183 .mutate_box()
184 .set_adjusted_display(new_display, false);
185 }
186
187 fn adjust_for_position(&mut self) {
193 if self.style.is_absolutely_positioned() && self.style.is_floating() {
194 self.style.mutate_box().set_float(Float::None);
195 }
196 }
197
198 fn skip_item_display_fixup<E>(&self, element: Option<E>) -> bool
201 where
202 E: TElement,
203 {
204 if let Some(pseudo) = self.style.pseudo {
205 return pseudo.skip_item_display_fixup();
206 }
207
208 element.is_some_and(|e| e.skip_item_display_fixup())
209 }
210
211 fn blockify_if_necessary<E>(&mut self, layout_parent_style: &ComputedValues, element: Option<E>)
218 where
219 E: TElement,
220 {
221 let mut blockify = false;
222 macro_rules! blockify_if {
223 ($if_what:expr) => {
224 if !blockify {
225 blockify = $if_what;
226 }
227 };
228 }
229
230 blockify_if!(self.style.is_root_element);
231 if !self.skip_item_display_fixup(element) {
232 let parent_display = layout_parent_style.get_box().clone_display();
233 blockify_if!(parent_display.is_item_container());
234 }
235
236 let is_item_or_root = blockify;
237
238 blockify_if!(self.style.is_floating());
239 blockify_if!(self.style.is_absolutely_positioned());
240
241 if !blockify {
242 return;
243 }
244
245 let display = self.style.get_box().clone_display();
246 let blockified_display = display.equivalent_block_display(self.style.is_root_element);
247 if display != blockified_display {
248 self.style
249 .mutate_box()
250 .set_adjusted_display(blockified_display, is_item_or_root);
251 }
252 }
253
254 fn set_bits(&mut self) {
256 let box_style = self.style.get_box();
257 let display = box_style.clone_display();
258
259 if !display.is_contents() {
260 if !self
261 .style
262 .get_text()
263 .clone_text_decoration_line()
264 .is_empty()
265 {
266 self.style
267 .add_flags(ComputedValueFlags::HAS_TEXT_DECORATION_LINES);
268 }
269
270 if self.style.get_effects().clone_opacity() == 0. {
271 self.style
272 .add_flags(ComputedValueFlags::IS_IN_OPACITY_ZERO_SUBTREE);
273 }
274 }
275
276 if self.style.pseudo.is_some_and(|p| p.is_first_line()) {
277 self.style
278 .add_flags(ComputedValueFlags::IS_IN_FIRST_LINE_SUBTREE);
279 }
280
281 if self.style.is_root_element {
282 self.style
283 .add_flags(ComputedValueFlags::IS_ROOT_ELEMENT_STYLE);
284 }
285
286 #[cfg(feature = "gecko")]
287 if box_style
288 .clone_effective_containment()
289 .contains(Contain::STYLE)
290 {
291 self.style
292 .add_flags(ComputedValueFlags::SELF_OR_ANCESTOR_HAS_CONTAIN_STYLE);
293 }
294
295 if box_style.clone_container_type().is_size_container_type() {
296 self.style
297 .add_flags(ComputedValueFlags::SELF_OR_ANCESTOR_HAS_SIZE_CONTAINER_TYPE);
298 }
299
300 #[cfg(feature = "servo")]
301 if self.style.get_parent_column().is_multicol() {
302 self.style.add_flags(ComputedValueFlags::CAN_BE_FRAGMENTED);
303 }
304 }
305
306 #[cfg(feature = "gecko")]
313 pub fn adjust_for_text(&mut self) {
314 debug_assert!(!self.style.is_root_element);
315 self.adjust_for_text_combine_upright();
316 self.adjust_for_text_in_ruby();
317 self.set_bits();
318 }
319
320 #[cfg(feature = "gecko")]
331 fn adjust_for_text_combine_upright(&mut self) {
332 use crate::computed_values::text_combine_upright::T as TextCombineUpright;
333 use crate::computed_values::writing_mode::T as WritingMode;
334 use crate::logical_geometry;
335
336 let writing_mode = self.style.get_inherited_box().clone_writing_mode();
337 let text_combine_upright = self.style.get_inherited_text().clone_text_combine_upright();
338
339 if matches!(
340 writing_mode,
341 WritingMode::VerticalRl | WritingMode::VerticalLr
342 ) && text_combine_upright == TextCombineUpright::All
343 {
344 self.style.add_flags(ComputedValueFlags::IS_TEXT_COMBINED);
345 self.style
346 .mutate_inherited_box()
347 .set_writing_mode(WritingMode::HorizontalTb);
348 self.style.writing_mode =
349 logical_geometry::WritingMode::new(self.style.get_inherited_box());
350 }
351 }
352
353 #[cfg(feature = "gecko")]
360 fn adjust_for_text_in_ruby(&mut self) {
361 let parent_display = self.style.get_parent_box().clone_display();
362 if parent_display.is_ruby_type()
363 || self
364 .style
365 .get_parent_flags()
366 .contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK)
367 {
368 self.style
369 .add_flags(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK);
370 }
371 }
372
373 fn adjust_for_writing_mode(&mut self, layout_parent_style: &ComputedValues) {
387 let our_writing_mode = self.style.get_inherited_box().clone_writing_mode();
388 let parent_writing_mode = layout_parent_style.get_inherited_box().clone_writing_mode();
389
390 if our_writing_mode != parent_writing_mode
391 && self.style.get_box().clone_display() == Display::Inline
392 {
393 if cfg!(feature = "servo") {
396 self.style
397 .mutate_box()
398 .set_adjusted_display(Display::InlineBlock, false);
399 } else {
400 self.style.mutate_box().set_display(Display::InlineBlock);
401 }
402 }
403 }
404
405 fn adjust_for_border_width(&mut self) {
410 properties::adjust_border_width(self.style);
411 }
412
413 #[cfg(feature = "gecko")]
416 fn adjust_for_column_rule_width(&mut self) {
417 let column_style = self.style.get_column();
418 if !column_style.clone_column_rule_style().none_or_hidden() {
419 return;
420 }
421 if !column_style.column_rule_has_nonzero_width() {
422 return;
423 }
424 self.style
425 .mutate_column()
426 .set_column_rule_width(crate::Zero::zero());
427 }
428
429 fn adjust_for_outline_width(&mut self) {
432 let outline = self.style.get_outline();
433 if !outline.clone_outline_style().none_or_hidden() {
434 return;
435 }
436 if !outline.outline_has_nonzero_width() {
437 return;
438 }
439 self.style
440 .mutate_outline()
441 .set_outline_width(crate::Zero::zero());
442 }
443
444 fn adjust_for_overflow(&mut self) {
450 let overflow_x = self.style.get_box().clone_overflow_x();
451 let overflow_y = self.style.get_box().clone_overflow_y();
452 if overflow_x == overflow_y {
453 return; }
455
456 if overflow_x.is_scrollable() != overflow_y.is_scrollable() {
457 let box_style = self.style.mutate_box();
458 box_style.set_overflow_x(overflow_x.to_scrollable());
459 box_style.set_overflow_y(overflow_y.to_scrollable());
460 }
461 }
462
463 #[cfg(feature = "gecko")]
464 fn adjust_for_contain(&mut self) {
465 let box_style = self.style.get_box();
466 let container_type = box_style.clone_container_type();
467 let content_visibility = box_style.clone_content_visibility();
468 if !container_type.is_size_container_type()
469 && content_visibility == ContentVisibility::Visible
470 {
471 debug_assert_eq!(
472 box_style.clone_contain(),
473 box_style.clone_effective_containment()
474 );
475 return;
476 }
477 let old_contain = box_style.clone_contain();
478 let mut new_contain = old_contain;
479 match content_visibility {
480 ContentVisibility::Visible => {},
481 ContentVisibility::Auto => {
485 new_contain.insert(Contain::LAYOUT | Contain::PAINT | Contain::STYLE)
486 },
487 ContentVisibility::Hidden => new_contain
488 .insert(Contain::LAYOUT | Contain::PAINT | Contain::SIZE | Contain::STYLE),
489 }
490 if container_type.intersects(ContainerType::INLINE_SIZE) {
491 new_contain.insert(Contain::STYLE | Contain::INLINE_SIZE);
495 } else if container_type.intersects(ContainerType::SIZE) {
496 new_contain.insert(Contain::STYLE | Contain::SIZE);
500 }
501 if new_contain == old_contain {
502 debug_assert_eq!(
503 box_style.clone_contain(),
504 box_style.clone_effective_containment()
505 );
506 return;
507 }
508 self.style
509 .mutate_box()
510 .set_effective_containment(new_contain);
511 }
512
513 #[cfg(feature = "gecko")]
518 fn adjust_for_contain_intrinsic_size(&mut self) {
519 let content_visibility = self.style.get_box().clone_content_visibility();
520 if content_visibility != ContentVisibility::Auto {
521 return;
522 }
523
524 let pos = self.style.get_position();
525 let new_width = pos.clone_contain_intrinsic_width().add_auto_if_needed();
526 let new_height = pos.clone_contain_intrinsic_height().add_auto_if_needed();
527 if new_width.is_none() && new_height.is_none() {
528 return;
529 }
530
531 let pos = self.style.mutate_position();
532 if let Some(width) = new_width {
533 pos.set_contain_intrinsic_width(width);
534 }
535 if let Some(height) = new_height {
536 pos.set_contain_intrinsic_height(height);
537 }
538 }
539
540 #[cfg(feature = "gecko")]
546 fn adjust_for_prohibited_display_contents<E>(&mut self, element: Option<E>)
547 where
548 E: TElement,
549 {
550 if self.style.get_box().clone_display() != Display::Contents {
551 return;
552 }
553
554 if self.style.pseudo.is_some_and(|p| !p.is_element_backed()) {
556 self.style.mutate_box().set_display(Display::Inline);
557 return;
558 }
559
560 let element = match element {
561 Some(e) => e,
562 None => return,
563 };
564
565 if is_effective_display_none_for_display_contents(element) {
566 self.style.mutate_box().set_display(Display::None);
567 }
568 }
569
570 #[cfg(feature = "gecko")]
573 fn adjust_for_text_control_editing_root(&mut self) {
574 use crate::properties::longhands::white_space_collapse::computed_value::T as WhiteSpaceCollapse;
575 use crate::selector_parser::PseudoElement;
576
577 if self.style.pseudo != Some(&PseudoElement::MozTextControlEditingRoot) {
578 return;
579 }
580
581 let old_collapse = self.style.get_inherited_text().clone_white_space_collapse();
582 let new_collapse = match old_collapse {
583 WhiteSpaceCollapse::Preserve | WhiteSpaceCollapse::BreakSpaces => old_collapse,
584 WhiteSpaceCollapse::Collapse
585 | WhiteSpaceCollapse::PreserveSpaces
586 | WhiteSpaceCollapse::PreserveBreaks => WhiteSpaceCollapse::Preserve,
587 };
588 if new_collapse != old_collapse {
589 self.style
590 .mutate_inherited_text()
591 .set_white_space_collapse(new_collapse);
592 }
593
594 let box_style = self.style.get_box();
595 let overflow_x = box_style.clone_overflow_x();
596 let overflow_y = box_style.clone_overflow_y();
597
598 if overflow_x.is_scrollable() || overflow_y.is_scrollable() {
601 return;
602 }
603
604 let box_style = self.style.mutate_box();
605 box_style.set_overflow_x(Overflow::Auto);
606 box_style.set_overflow_y(Overflow::Auto);
607 }
608
609 #[cfg(feature = "gecko")]
616 fn adjust_for_fieldset_content(&mut self, layout_parent_style: &ComputedValues) {
617 use crate::selector_parser::PseudoElement;
618
619 if self.style.pseudo != Some(&PseudoElement::FieldsetContent) {
620 return;
621 }
622
623 let parent_display = layout_parent_style.get_box().clone_display();
627 let new_display = match parent_display {
628 Display::Flex | Display::InlineFlex => Some(Display::Flex),
629 Display::Grid | Display::InlineGrid => Some(Display::Grid),
630 _ => None,
631 };
632 if let Some(new_display) = new_display {
633 self.style.mutate_box().set_display(new_display);
634 }
635 }
636
637 fn adjust_for_table_text_align(&mut self) {
644 use crate::properties::longhands::text_align::computed_value::T as TextAlign;
645 if self.style.get_box().clone_display() != Display::Table {
646 return;
647 }
648
649 match self.style.get_inherited_text().clone_text_align() {
650 TextAlign::MozLeft | TextAlign::MozCenter | TextAlign::MozRight => {},
651 _ => return,
652 }
653
654 self.style
655 .mutate_inherited_text()
656 .set_text_align(TextAlign::Start)
657 }
658
659 #[cfg(feature = "gecko")]
660 fn should_suppress_linebreak<E>(
661 &self,
662 layout_parent_style: &ComputedValues,
663 element: Option<E>,
664 ) -> bool
665 where
666 E: TElement,
667 {
668 if self.style.is_floating() || self.style.is_absolutely_positioned() {
670 return false;
671 }
672 let parent_display = layout_parent_style.get_box().clone_display();
673 if layout_parent_style
674 .flags
675 .contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK)
676 {
677 if parent_display.is_line_participant() {
680 return true;
681 }
682 }
683 match self.style.get_box().clone_display() {
684 Display::RubyBase | Display::RubyText => true,
686 Display::RubyBaseContainer | Display::RubyTextContainer
695 if element.map_or(true, |e| e.is_html_element()) =>
696 {
697 false
698 },
699 _ => parent_display.is_ruby_type(),
703 }
704 }
705
706 #[cfg(feature = "gecko")]
712 fn adjust_for_ruby<E>(&mut self, layout_parent_style: &ComputedValues, element: Option<E>)
713 where
714 E: TElement,
715 {
716 use crate::properties::longhands::unicode_bidi::computed_value::T as UnicodeBidi;
717
718 let self_display = self.style.get_box().clone_display();
719 if self.should_suppress_linebreak(layout_parent_style, element) {
721 self.style
722 .add_flags(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK);
723 if !self.skip_item_display_fixup(element) {
725 let inline_display = self_display.inlinify();
726 if self_display != inline_display {
727 self.style
728 .mutate_box()
729 .set_adjusted_display(inline_display, false);
730 }
731 }
732 }
733 if self_display.is_ruby_level_container() {
738 self.style.reset_border_struct();
739 self.style.reset_padding_struct();
740 }
741
742 if self_display.is_ruby_type() {
745 let new_value = match self.style.get_text().clone_unicode_bidi() {
746 UnicodeBidi::Normal | UnicodeBidi::Embed => Some(UnicodeBidi::Isolate),
747 UnicodeBidi::BidiOverride => Some(UnicodeBidi::IsolateOverride),
748 _ => None,
749 };
750 if let Some(new_value) = new_value {
751 self.style.mutate_text().set_unicode_bidi(new_value);
752 }
753 }
754 }
755
756 fn adjust_for_visited<E>(&mut self, element: Option<E>)
766 where
767 E: TElement,
768 {
769 if !self.style.has_visited_style() {
770 return;
771 }
772
773 let is_link_element = self.style.pseudo.is_none() && element.map_or(false, |e| e.is_link());
774
775 if !is_link_element {
776 return;
777 }
778
779 if element.unwrap().is_visited_link() {
780 self.style
781 .add_flags(ComputedValueFlags::IS_RELEVANT_LINK_VISITED);
782 } else {
783 self.style
785 .remove_flags(ComputedValueFlags::IS_RELEVANT_LINK_VISITED);
786 }
787 }
788
789 #[cfg(feature = "gecko")]
794 fn adjust_for_justify_items(&mut self) {
795 use crate::values::specified::align;
796 let justify_items = self.style.get_position().clone_justify_items();
797 if justify_items.specified.0 != align::AlignFlags::LEGACY {
798 return;
799 }
800
801 let parent_justify_items = self.style.get_parent_position().clone_justify_items();
802
803 if !parent_justify_items
804 .computed
805 .0
806 .contains(align::AlignFlags::LEGACY)
807 {
808 return;
809 }
810
811 if parent_justify_items.computed == justify_items.computed {
812 return;
813 }
814
815 self.style
816 .mutate_position()
817 .set_computed_justify_items(parent_justify_items.computed);
818 }
819
820 #[cfg(feature = "gecko")]
825 fn adjust_for_appearance<E>(&mut self, element: Option<E>)
826 where
827 E: TElement,
828 {
829 use crate::properties::longhands::appearance::computed_value::T as Appearance;
830 use crate::properties::longhands::line_height::computed_value::T as LineHeight;
831
832 let box_ = self.style.get_box();
833 let appearance = match box_.clone_appearance() {
834 Appearance::Auto => box_.clone__moz_default_appearance(),
835 a => a,
836 };
837
838 if appearance == Appearance::Menulist {
839 if self.style.get_font().clone_line_height() == LineHeight::normal() {
840 return;
841 }
842 if self.style.pseudo.is_some() {
843 return;
844 }
845 let is_html_select_element = element.map_or(false, |e| {
846 e.is_html_element() && e.local_name() == &*atom!("select")
847 });
848 if !is_html_select_element {
849 return;
850 }
851 self.style
852 .mutate_font()
853 .set_line_height(LineHeight::normal());
854 }
855 }
856
857 #[cfg(feature = "gecko")]
868 fn adjust_for_marker_pseudo(&mut self) {
869 use crate::values::computed::counters::Content;
870 use crate::values::computed::font::{FontFamily, FontSynthesis, FontSynthesisStyle};
871 use crate::values::computed::text::{LetterSpacing, WordSpacing};
872
873 let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker())
874 && self.style.get_list().clone_list_style_type().is_bullet()
875 && self.style.get_counters().clone_content() == Content::Normal;
876 if !is_legacy_marker {
877 return;
878 }
879 let flags = self.style.flags.get();
880 if !flags.contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY) {
881 self.style
882 .mutate_font()
883 .set_font_family(FontFamily::moz_bullet().clone());
884
885 if !flags.contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS_WEIGHT) {
889 self.style
890 .mutate_font()
891 .set_font_synthesis_weight(FontSynthesis::None);
892 }
893 if !flags.contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS_STYLE) {
894 self.style
895 .mutate_font()
896 .set_font_synthesis_style(FontSynthesisStyle::None);
897 }
898 }
899 if !flags.contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING) {
900 self.style
901 .mutate_inherited_text()
902 .set_letter_spacing(LetterSpacing::normal());
903 }
904 if !flags.contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING) {
905 self.style
906 .mutate_inherited_text()
907 .set_word_spacing(WordSpacing::normal());
908 }
909 }
910
911 pub fn adjust<E>(&mut self, layout_parent_style: &ComputedValues, element: Option<E>)
918 where
919 E: TElement,
920 {
921 if cfg!(debug_assertions) {
922 if let Some(e) = element {
923 if let Some(p) = e.implemented_pseudo_element() {
924 debug_assert!(
928 self.style.pseudo.is_some(),
929 "Someone really messed up (no pseudo style for {e:?}, {p:?})"
930 );
931 }
932 }
933 }
934 self.adjust_for_visited(element);
944 #[cfg(feature = "gecko")]
945 {
946 self.adjust_for_prohibited_display_contents(element);
947 self.adjust_for_fieldset_content(layout_parent_style);
948 self.adjust_for_text_control_editing_root();
951 }
952 self.adjust_for_top_layer();
953 self.blockify_if_necessary(layout_parent_style, element);
954 #[cfg(feature = "gecko")]
955 self.adjust_for_webkit_line_clamp();
956 self.adjust_for_position();
957 self.adjust_for_overflow();
958 #[cfg(feature = "gecko")]
959 {
960 self.adjust_for_contain();
961 self.adjust_for_contain_intrinsic_size();
962 self.adjust_for_justify_items();
963 }
964 self.adjust_for_table_text_align();
965 self.adjust_for_border_width();
966 #[cfg(feature = "gecko")]
967 self.adjust_for_column_rule_width();
968 self.adjust_for_outline_width();
969 self.adjust_for_writing_mode(layout_parent_style);
970 #[cfg(feature = "gecko")]
971 {
972 self.adjust_for_ruby(layout_parent_style, element);
973 self.adjust_for_appearance(element);
974 self.adjust_for_marker_pseudo();
975 }
976 self.set_bits();
977 }
978}