mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
merge from master
This commit is contained in:
commit
6e774ea6eb
1044 changed files with 46059 additions and 1506 deletions
|
@ -340,6 +340,10 @@ impl CandidateBSizeIterator {
|
|||
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
||||
Some(block_container_block_size.scale_by(percent))
|
||||
}
|
||||
(LengthOrPercentageOrNone::Calc(calc), Some(block_container_block_size)) => {
|
||||
Some(block_container_block_size.scale_by(calc.percentage()) + calc.length())
|
||||
}
|
||||
(LengthOrPercentageOrNone::Calc(_), _) |
|
||||
(LengthOrPercentageOrNone::Percentage(_), None) |
|
||||
(LengthOrPercentageOrNone::None, _) => None,
|
||||
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
||||
|
@ -1024,17 +1028,12 @@ impl BlockFlow {
|
|||
let mut candidate_block_size_iterator = CandidateBSizeIterator::new(
|
||||
&self.fragment,
|
||||
self.base.block_container_explicit_block_size);
|
||||
loop {
|
||||
match candidate_block_size_iterator.next() {
|
||||
Some(candidate_block_size) => {
|
||||
candidate_block_size_iterator.candidate_value =
|
||||
match candidate_block_size {
|
||||
MaybeAuto::Auto => block_size,
|
||||
MaybeAuto::Specified(value) => value
|
||||
}
|
||||
while let Some(candidate_block_size) = candidate_block_size_iterator.next() {
|
||||
candidate_block_size_iterator.candidate_value =
|
||||
match candidate_block_size {
|
||||
MaybeAuto::Auto => block_size,
|
||||
MaybeAuto::Specified(value) => value
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust `cur_b` as necessary to account for the explicitly-specified block-size.
|
||||
|
|
|
@ -27,6 +27,7 @@ use std::{fmt, isize, mem};
|
|||
use style::computed_values::{display, overflow_x, position, text_align, text_justify};
|
||||
use style::computed_values::{text_overflow, vertical_align, white_space};
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::LengthOrPercentage;
|
||||
use text;
|
||||
use unicode_bidi;
|
||||
use util;
|
||||
|
@ -953,15 +954,15 @@ impl InlineFlow {
|
|||
offset_from_baseline = offset_from_baseline - *depth_below_baseline
|
||||
}
|
||||
},
|
||||
vertical_align::T::Length(length) => {
|
||||
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Length(length)) => {
|
||||
offset_from_baseline = offset_from_baseline - length
|
||||
}
|
||||
vertical_align::T::Percentage(p) => {
|
||||
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Percentage(p)) => {
|
||||
let line_height = fragment.calculate_line_height(layout_context);
|
||||
let percent_offset = line_height.scale_by(p);
|
||||
offset_from_baseline = offset_from_baseline - percent_offset
|
||||
}
|
||||
vertical_align::T::Calc(calc) => {
|
||||
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Calc(calc)) => {
|
||||
let line_height = fragment.calculate_line_height(layout_context);
|
||||
let percent_offset = line_height.scale_by(calc.percentage());
|
||||
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
||||
|
|
|
@ -51,9 +51,7 @@ use profile_traits::time::{self, ProfilerMetadata, profile};
|
|||
use query::{LayoutRPCImpl, process_content_box_request, process_content_boxes_request};
|
||||
use query::{MarginPadding, MarginRetrievingFragmentBorderBoxIterator, PositionProperty};
|
||||
use query::{PositionRetrievingFragmentBorderBoxIterator, Side};
|
||||
use script::dom::bindings::js::LayoutJS;
|
||||
use script::dom::document::Document;
|
||||
use script::dom::node::{LayoutData, Node};
|
||||
use script::dom::node::LayoutData;
|
||||
use script::layout_interface::Animation;
|
||||
use script::layout_interface::{LayoutChan, LayoutRPC, OffsetParentResponse};
|
||||
use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType};
|
||||
|
@ -90,7 +88,7 @@ use util::opts;
|
|||
use util::task::spawn_named_with_send_on_failure;
|
||||
use util::task_state;
|
||||
use util::workqueue::WorkQueue;
|
||||
use wrapper::{LayoutDocument, LayoutNode, ThreadSafeLayoutNode};
|
||||
use wrapper::{LayoutNode, ThreadSafeLayoutNode};
|
||||
|
||||
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
||||
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
|
||||
|
@ -595,7 +593,7 @@ impl LayoutTask {
|
|||
profile(time::ProfilerCategory::LayoutPerform,
|
||||
self.profiler_metadata(),
|
||||
self.time_profiler_chan.clone(),
|
||||
|| self.handle_reflow(&*data, possibly_locked_rw_data));
|
||||
|| self.handle_reflow(&data, possibly_locked_rw_data));
|
||||
},
|
||||
Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data),
|
||||
Msg::ReflowWithNewlyLoadedWebFont => {
|
||||
|
@ -892,17 +890,9 @@ impl LayoutTask {
|
|||
property: &Atom,
|
||||
layout_root: &mut FlowRef)
|
||||
-> Option<String> {
|
||||
// FIXME: Isolate this transmutation into a "bridge" module.
|
||||
// FIXME(rust#16366): The following line had to be moved because of a
|
||||
// rustc bug. It should be in the next unsafe block.
|
||||
let node: LayoutJS<Node> = unsafe {
|
||||
LayoutJS::from_trusted_node_address(requested_node)
|
||||
};
|
||||
let node: &LayoutNode = unsafe {
|
||||
transmute(&node)
|
||||
};
|
||||
let node = unsafe { LayoutNode::new(&requested_node) };
|
||||
|
||||
let layout_node = ThreadSafeLayoutNode::new(node);
|
||||
let layout_node = ThreadSafeLayoutNode::new(&node);
|
||||
let layout_node = match pseudo {
|
||||
&Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
|
||||
&Some(PseudoElement::After) => layout_node.get_after_pseudo(),
|
||||
|
@ -1133,15 +1123,9 @@ impl LayoutTask {
|
|||
};
|
||||
let _ajst = AutoJoinScriptTask { data: data };
|
||||
|
||||
// FIXME: Isolate this transmutation into a "bridge" module.
|
||||
let mut doc: LayoutJS<Document> = unsafe {
|
||||
LayoutJS::from_trusted_node_address(data.document).downcast::<Document>().unwrap()
|
||||
};
|
||||
let doc: &mut LayoutDocument = unsafe {
|
||||
transmute(&mut doc)
|
||||
};
|
||||
|
||||
let mut node: LayoutNode = match doc.root_node() {
|
||||
let document = unsafe { LayoutNode::new(&data.document) };
|
||||
let document = document.as_document().unwrap();
|
||||
let node: LayoutNode = match document.root_node() {
|
||||
None => return,
|
||||
Some(x) => x,
|
||||
};
|
||||
|
@ -1187,7 +1171,7 @@ impl LayoutTask {
|
|||
let needs_reflow = screen_size_changed && !needs_dirtying;
|
||||
unsafe {
|
||||
if needs_dirtying {
|
||||
LayoutTask::dirty_all_nodes(&mut node);
|
||||
LayoutTask::dirty_all_nodes(node);
|
||||
}
|
||||
}
|
||||
if needs_reflow {
|
||||
|
@ -1196,11 +1180,12 @@ impl LayoutTask {
|
|||
}
|
||||
}
|
||||
|
||||
let event_state_changes = doc.drain_event_state_changes();
|
||||
let state_changes = document.drain_element_state_changes();
|
||||
if !needs_dirtying {
|
||||
for &(el, state) in event_state_changes.iter() {
|
||||
assert!(!state.is_empty());
|
||||
el.note_event_state_change();
|
||||
for &(el, state_change) in state_changes.iter() {
|
||||
debug_assert!(!state_change.is_empty());
|
||||
let hint = rw_data.stylist.restyle_hint_for_state_change(&el, el.get_state(), state_change);
|
||||
el.note_restyle_hint(hint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1214,7 @@ impl LayoutTask {
|
|||
});
|
||||
|
||||
// Retrieve the (possibly rebuilt) root flow.
|
||||
rw_data.root_flow = self.try_get_layout_root(node.clone());
|
||||
rw_data.root_flow = self.try_get_layout_root(node);
|
||||
}
|
||||
|
||||
// Send new canvas renderers to the paint task
|
||||
|
@ -1459,7 +1444,7 @@ impl LayoutTask {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn dirty_all_nodes(node: &mut LayoutNode) {
|
||||
unsafe fn dirty_all_nodes(node: LayoutNode) {
|
||||
for node in node.traverse_preorder() {
|
||||
// TODO(cgaebel): mark nodes which are sensitive to media queries as
|
||||
// "changed":
|
||||
|
|
|
@ -47,7 +47,7 @@ extern crate net_traits;
|
|||
extern crate rustc_serialize;
|
||||
extern crate script;
|
||||
extern crate script_traits;
|
||||
extern crate selectors;
|
||||
#[macro_use(state_pseudo_classes)] extern crate selectors;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate smallvec;
|
||||
|
|
|
@ -411,6 +411,8 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
|
|||
match length {
|
||||
LengthOrPercentageOrNone::None => None,
|
||||
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
|
||||
LengthOrPercentageOrNone::Calc(calc) =>
|
||||
Some(containing_length.scale_by(calc.percentage()) + calc.length()),
|
||||
LengthOrPercentageOrNone::Length(length) => Some(length),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@ use script::dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
|
|||
use script::dom::bindings::js::LayoutJS;
|
||||
use script::dom::characterdata::LayoutCharacterDataHelpers;
|
||||
use script::dom::document::{Document, LayoutDocumentHelpers};
|
||||
use script::dom::element;
|
||||
use script::dom::element::{Element, EventState, LayoutElementHelpers, RawLayoutElementHelpers};
|
||||
use script::dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
|
||||
use script::dom::htmlcanvaselement::{LayoutHTMLCanvasElementHelpers, HTMLCanvasData};
|
||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
||||
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
||||
|
@ -52,8 +51,10 @@ use script::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaEl
|
|||
use script::dom::node::{HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY};
|
||||
use script::dom::node::{LayoutNodeHelpers, Node, SharedLayoutData};
|
||||
use script::dom::text::Text;
|
||||
use script::layout_interface::TrustedNodeAddress;
|
||||
use selectors::matching::DeclarationBlock;
|
||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||
use selectors::states::*;
|
||||
use smallvec::VecLike;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::{Ref, RefMut};
|
||||
|
@ -68,6 +69,7 @@ use style::legacy::UnsignedIntegerAttribute;
|
|||
use style::node::TElementAttributes;
|
||||
use style::properties::ComputedValues;
|
||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use style::restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
||||
use url::Url;
|
||||
use util::str::{is_whitespace, search_index};
|
||||
|
||||
|
@ -79,7 +81,7 @@ pub struct LayoutNode<'a> {
|
|||
node: LayoutJS<Node>,
|
||||
|
||||
/// Being chained to a PhantomData prevents `LayoutNode`s from escaping.
|
||||
pub chain: PhantomData<&'a ()>,
|
||||
chain: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for LayoutNode<'a> {
|
||||
|
@ -90,6 +92,14 @@ impl<'a> PartialEq for LayoutNode<'a> {
|
|||
}
|
||||
|
||||
impl<'ln> LayoutNode<'ln> {
|
||||
pub unsafe fn new(address: &TrustedNodeAddress) -> LayoutNode {
|
||||
let node = LayoutJS::from_trusted_node_address(*address);
|
||||
LayoutNode {
|
||||
node: node,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new layout node with the same lifetime as this layout node.
|
||||
pub unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> LayoutNode<'ln> {
|
||||
LayoutNode {
|
||||
|
@ -205,6 +215,15 @@ impl<'ln> LayoutNode<'ln> {
|
|||
as_element(self.node)
|
||||
}
|
||||
|
||||
pub fn as_document(&self) -> Option<LayoutDocument<'ln>> {
|
||||
self.node.downcast().map(|document| {
|
||||
LayoutDocument {
|
||||
document: document,
|
||||
chain: PhantomData,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
||||
unsafe {
|
||||
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
|
@ -353,16 +372,12 @@ impl<'le> LayoutDocument<'le> {
|
|||
}
|
||||
|
||||
pub fn root_node(&self) -> Option<LayoutNode<'le>> {
|
||||
let mut node = self.as_node().first_child();
|
||||
while node.is_some() && !node.unwrap().is_element() {
|
||||
node = node.unwrap().next_sibling();
|
||||
}
|
||||
node
|
||||
self.as_node().children().find(LayoutNode::is_element)
|
||||
}
|
||||
|
||||
pub fn drain_event_state_changes(&self) -> Vec<(LayoutElement, EventState)> {
|
||||
pub fn drain_element_state_changes(&self) -> Vec<(LayoutElement, ElementState)> {
|
||||
unsafe {
|
||||
let changes = self.document.drain_event_state_changes();
|
||||
let changes = self.document.drain_element_state_changes();
|
||||
Vec::from_iter(changes.iter().map(|&(el, state)|
|
||||
(LayoutElement {
|
||||
element: el,
|
||||
|
@ -393,39 +408,58 @@ impl<'le> LayoutElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Properly marks nodes as dirty in response to event state changes.
|
||||
///
|
||||
/// Currently this implementation is very conservative, and basically mirrors node::dirty_impl.
|
||||
/// With restyle hints, we can do less work here.
|
||||
pub fn note_event_state_change(&self) {
|
||||
let node = self.as_node();
|
||||
pub fn get_state(&self) -> ElementState {
|
||||
self.element.get_state_for_layout()
|
||||
}
|
||||
|
||||
// Bail out if we're already dirty. This won't be valid when we start doing more targeted
|
||||
// dirtying with restyle hints.
|
||||
if node.is_dirty() { return }
|
||||
|
||||
// Dirty descendants.
|
||||
fn dirty_subtree(node: LayoutNode) {
|
||||
// Stop if this subtree is already dirty. This won't be valid with restyle hints, see above.
|
||||
if node.is_dirty() { return }
|
||||
|
||||
unsafe {
|
||||
node.set_dirty(true);
|
||||
node.set_dirty_descendants(true);
|
||||
}
|
||||
|
||||
for kid in node.children() {
|
||||
dirty_subtree(kid);
|
||||
}
|
||||
/// Properly marks nodes as dirty in response to restyle hints.
|
||||
pub fn note_restyle_hint(&self, hint: RestyleHint) {
|
||||
// Bail early if there's no restyling to do.
|
||||
if hint.is_empty() {
|
||||
return;
|
||||
}
|
||||
dirty_subtree(node);
|
||||
|
||||
// If the restyle hint is non-empty, we need to restyle either this element
|
||||
// or one of its siblings. Mark our ancestor chain as having dirty descendants.
|
||||
let node = self.as_node();
|
||||
let mut curr = node;
|
||||
while let Some(parent) = curr.parent_node() {
|
||||
if parent.has_dirty_descendants() { break }
|
||||
unsafe { parent.set_dirty_descendants(true); }
|
||||
curr = parent;
|
||||
}
|
||||
|
||||
// Set up our helpers.
|
||||
fn dirty_node(node: &LayoutNode) {
|
||||
unsafe {
|
||||
node.set_dirty(true);
|
||||
node.set_dirty_descendants(true);
|
||||
}
|
||||
}
|
||||
fn dirty_descendants(node: &LayoutNode) {
|
||||
for ref child in node.children() {
|
||||
dirty_node(child);
|
||||
dirty_descendants(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Process hints.
|
||||
if hint.contains(RESTYLE_SELF) {
|
||||
dirty_node(&node);
|
||||
}
|
||||
if hint.contains(RESTYLE_DESCENDANTS) {
|
||||
unsafe { node.set_dirty_descendants(true); }
|
||||
dirty_descendants(&node);
|
||||
}
|
||||
if hint.contains(RESTYLE_LATER_SIBLINGS) {
|
||||
let mut next = ::selectors::Element::next_sibling_element(self);
|
||||
while let Some(sib) = next {
|
||||
let sib_node = sib.as_node();
|
||||
dirty_node(&sib_node);
|
||||
dirty_descendants(&sib_node);
|
||||
next = ::selectors::Element::next_sibling_element(&sib);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,6 +472,15 @@ fn as_element<'le>(node: LayoutJS<Node>) -> Option<LayoutElement<'le>> {
|
|||
})
|
||||
}
|
||||
|
||||
macro_rules! state_getter {
|
||||
($(
|
||||
$(#[$Flag_attr: meta])*
|
||||
state $css: expr => $variant: ident / $method: ident /
|
||||
$flag: ident = $value: expr,
|
||||
)+) => {
|
||||
$( fn $method(&self) -> bool { self.element.get_state_for_layout().contains($flag) } )+
|
||||
}
|
||||
}
|
||||
|
||||
impl<'le> ::selectors::Element for LayoutElement<'le> {
|
||||
fn parent_element(&self) -> Option<LayoutElement<'le>> {
|
||||
|
@ -529,20 +572,7 @@ impl<'le> ::selectors::Element for LayoutElement<'le> {
|
|||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_hover_state(&self) -> bool {
|
||||
self.element.get_event_state_for_layout().contains(element::IN_HOVER_STATE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_focus_state(&self) -> bool {
|
||||
self.element.get_event_state_for_layout().contains(element::IN_FOCUS_STATE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_active_state(&self) -> bool {
|
||||
self.element.get_event_state_for_layout().contains(element::IN_ACTIVE_STATE)
|
||||
}
|
||||
state_pseudo_classes!(state_getter);
|
||||
|
||||
#[inline]
|
||||
fn get_id(&self) -> Option<Atom> {
|
||||
|
@ -551,26 +581,6 @@ impl<'le> ::selectors::Element for LayoutElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_disabled_state(&self) -> bool {
|
||||
self.element.get_event_state_for_layout().contains(element::IN_DISABLED_STATE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_enabled_state(&self) -> bool {
|
||||
self.element.get_event_state_for_layout().contains(element::IN_ENABLED_STATE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_checked_state(&self) -> bool {
|
||||
self.element.get_checked_state_for_layout()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_indeterminate_state(&self) -> bool {
|
||||
self.element.get_indeterminate_state_for_layout()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_class(&self, name: &Atom) -> bool {
|
||||
unsafe {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue