gecko-dev/servo/components/layout/incremental.rs
Pu Xingyu 75700f6496 servo: Merge #16458 - layout: Force reflow in the sequential fallback of block format context (from stshine:sequential-fallback); r=pcwalton,emilio
When reflowing a block format context during the inorder traversal,
propagate restyle damage manually to its children since they were
already reflowed. Also, test the border box to see if it can fit into
floats according to CSS 2.1 § 9.5.

Improves reddit and yahoo.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 541db5f9a791f52e22d409d3b40b13223df69b4c

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 2a1bb98d251df29f460e9ab379d27d1fd49febf7
2017-04-22 23:55:22 -05:00

87 lines
3.5 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, IS_ABSOLUTELY_POSITIONED};
use style::computed_values::float;
use style::selector_parser::RestyleDamage;
use style::servo::restyle_damage::{REFLOW, RECONSTRUCT_FLOW};
/// Used in a flow traversal to indicate whether this re-layout should be incremental or not.
#[derive(Clone, Copy, PartialEq)]
pub enum RelayoutMode {
Incremental,
Force
}
bitflags! {
pub flags SpecialRestyleDamage: u8 {
#[doc = "If this flag is set, we need to reflow the entire document. This is more or less a \
temporary hack to deal with cases that we don't handle incrementally yet."]
const REFLOW_ENTIRE_DOCUMENT = 0x01,
}
}
pub trait LayoutDamageComputation {
fn compute_layout_damage(self) -> SpecialRestyleDamage;
fn reflow_entire_document(self);
}
impl<'a> LayoutDamageComputation for &'a mut Flow {
fn compute_layout_damage(self) -> SpecialRestyleDamage {
let mut special_damage = SpecialRestyleDamage::empty();
let is_absolutely_positioned = flow::base(self).flags.contains(IS_ABSOLUTELY_POSITIONED);
// In addition to damage, we use this phase to compute whether nodes affect CSS counters.
let mut has_counter_affecting_children = false;
{
let self_base = flow::mut_base(self);
// Take a snapshot of the parent damage before updating it with damage from children.
let parent_damage = self_base.restyle_damage;
for kid in self_base.children.iter_mut() {
let child_is_absolutely_positioned =
flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED);
flow::mut_base(kid).restyle_damage.insert(
parent_damage.damage_for_child(is_absolutely_positioned,
child_is_absolutely_positioned));
{
let kid: &mut Flow = kid;
special_damage.insert(kid.compute_layout_damage());
}
self_base.restyle_damage
.insert(flow::base(kid).restyle_damage.damage_for_parent(
child_is_absolutely_positioned));
has_counter_affecting_children = has_counter_affecting_children ||
flow::base(kid).flags.intersects(AFFECTS_COUNTERS |
HAS_COUNTER_AFFECTING_CHILDREN);
}
}
let self_base = flow::mut_base(self);
if self_base.flags.float_kind() != float::T::none &&
self_base.restyle_damage.intersects(REFLOW) {
special_damage.insert(REFLOW_ENTIRE_DOCUMENT);
}
if has_counter_affecting_children {
self_base.flags.insert(HAS_COUNTER_AFFECTING_CHILDREN)
} else {
self_base.flags.remove(HAS_COUNTER_AFFECTING_CHILDREN)
}
special_damage
}
fn reflow_entire_document(self) {
let self_base = flow::mut_base(self);
self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow());
self_base.restyle_damage.remove(RECONSTRUCT_FLOW);
for kid in self_base.children.iter_mut() {
kid.reflow_entire_document();
}
}
}