merge from master

This commit is contained in:
rohan.prinja 2015-11-03 19:01:23 +09:00
commit 6e774ea6eb
1044 changed files with 46059 additions and 1506 deletions

View file

@ -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.

View file

@ -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()

View file

@ -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":

View file

@ -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;

View file

@ -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),
}
}

View file

@ -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 {