mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
layout: Address review feedback.
This commit is contained in:
parent
30b7f5d0ad
commit
c49f23ffb2
25 changed files with 296 additions and 303 deletions
|
@ -23,8 +23,6 @@ use servo_net::image::base::Image;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use servo_util::smallvec::{SmallVec, SmallVec0, SmallVecIterator};
|
use servo_util::smallvec::{SmallVec, SmallVec0, SmallVecIterator};
|
||||||
use std::cast::transmute_region;
|
|
||||||
use std::cast;
|
|
||||||
use std::libc::uintptr_t;
|
use std::libc::uintptr_t;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::vec::Items;
|
use std::vec::Items;
|
||||||
|
@ -43,9 +41,8 @@ pub struct OpaqueNode(uintptr_t);
|
||||||
impl OpaqueNode {
|
impl OpaqueNode {
|
||||||
/// Returns the address of this node, for debugging purposes.
|
/// Returns the address of this node, for debugging purposes.
|
||||||
pub fn id(&self) -> uintptr_t {
|
pub fn id(&self) -> uintptr_t {
|
||||||
unsafe {
|
let OpaqueNode(pointer) = *self;
|
||||||
cast::transmute_copy(self)
|
pointer
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,16 +425,13 @@ impl DisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base<'a>(&'a self) -> &'a BaseDisplayItem {
|
pub fn base<'a>(&'a self) -> &'a BaseDisplayItem {
|
||||||
// FIXME(tkuehn): Workaround for Rust region bug.
|
match *self {
|
||||||
unsafe {
|
SolidColorDisplayItemClass(ref solid_color) => &solid_color.base,
|
||||||
match *self {
|
TextDisplayItemClass(ref text) => &text.base,
|
||||||
SolidColorDisplayItemClass(ref solid_color) => transmute_region(&solid_color.base),
|
ImageDisplayItemClass(ref image_item) => &image_item.base,
|
||||||
TextDisplayItemClass(ref text) => transmute_region(&text.base),
|
BorderDisplayItemClass(ref border) => &border.base,
|
||||||
ImageDisplayItemClass(ref image_item) => transmute_region(&image_item.base),
|
LineDisplayItemClass(ref line) => &line.base,
|
||||||
BorderDisplayItemClass(ref border) => transmute_region(&border.base),
|
ClipDisplayItemClass(ref clip) => &clip.base,
|
||||||
LineDisplayItemClass(ref line) => transmute_region(&line.base),
|
|
||||||
ClipDisplayItemClass(ref clip) => transmute_region(&clip.base),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,9 @@ pub struct RenderLayer {
|
||||||
/// The display list describing the contents of this layer.
|
/// The display list describing the contents of this layer.
|
||||||
display_list: Arc<DisplayList>,
|
display_list: Arc<DisplayList>,
|
||||||
/// The position of the layer in pixels.
|
/// The position of the layer in pixels.
|
||||||
rect: Rect<uint>,
|
position: Rect<uint>,
|
||||||
/// The color of the background in this layer. Used for unrendered content.
|
/// The color of the background in this layer. Used for unrendered content.
|
||||||
color: Color,
|
background_color: Color,
|
||||||
/// The scrolling policy of this layer.
|
/// The scrolling policy of this layer.
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferReq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): This should be a newtype struct.
|
// FIXME(#2005, pcwalton): This should be a newtype struct.
|
||||||
pub struct RenderChan {
|
pub struct RenderChan {
|
||||||
chan: Chan<Msg>,
|
chan: Chan<Msg>,
|
||||||
}
|
}
|
||||||
|
@ -157,8 +157,8 @@ fn initialize_layers<C:RenderListener>(
|
||||||
let metadata = render_layers.iter().map(|render_layer| {
|
let metadata = render_layers.iter().map(|render_layer| {
|
||||||
LayerMetadata {
|
LayerMetadata {
|
||||||
id: render_layer.id,
|
id: render_layer.id,
|
||||||
rect: render_layer.rect,
|
position: render_layer.position,
|
||||||
color: render_layer.color,
|
background_color: render_layer.background_color,
|
||||||
scroll_policy: render_layer.scroll_policy,
|
scroll_policy: render_layer.scroll_policy,
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
@ -297,14 +297,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
let mut new_buffers = ~[];
|
let mut new_buffers = ~[];
|
||||||
|
|
||||||
// Find the appropriate render layer.
|
// Find the appropriate render layer.
|
||||||
let mut render_layer = None;
|
let render_layer = match self.render_layers.iter().find(|layer| layer.id == layer_id) {
|
||||||
for layer in self.render_layers.iter() {
|
|
||||||
if layer.id == layer_id {
|
|
||||||
render_layer = Some(layer);
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let render_layer = match render_layer {
|
|
||||||
Some(render_layer) => render_layer,
|
Some(render_layer) => render_layer,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
@ -349,14 +342,14 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
|
let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
|
||||||
let matrix = matrix.translate(-(tile.page_rect.origin.x) as AzFloat,
|
let matrix = matrix.translate(-(tile.page_rect.origin.x) as AzFloat,
|
||||||
-(tile.page_rect.origin.y) as AzFloat);
|
-(tile.page_rect.origin.y) as AzFloat);
|
||||||
let matrix = matrix.translate(-(render_layer.rect.origin.x as AzFloat),
|
let matrix = matrix.translate(-(render_layer.position.origin.x as AzFloat),
|
||||||
-(render_layer.rect.origin.y as AzFloat));
|
-(render_layer.position.origin.y as AzFloat));
|
||||||
|
|
||||||
ctx.draw_target.set_transform(&matrix);
|
ctx.draw_target.set_transform(&matrix);
|
||||||
|
|
||||||
// Clear the buffer.
|
// Clear the buffer.
|
||||||
ctx.clear();
|
ctx.clear();
|
||||||
|
|
||||||
// Draw the display list.
|
// Draw the display list.
|
||||||
profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
|
profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
|
||||||
render_layer.display_list.get().draw_into_context(&mut ctx);
|
render_layer.display_list.get().draw_into_context(&mut ctx);
|
||||||
|
@ -429,7 +422,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new_buffers.push(buffer);
|
new_buffers.push(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,7 @@ impl IOCompositor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Take the pipeline ID and layer ID into account.
|
// FIXME(#2004, pcwalton): Take the pipeline ID and layer ID into account.
|
||||||
fn set_unrendered_color(&mut self, _: PipelineId, _: LayerId, color: Color) {
|
fn set_unrendered_color(&mut self, _: PipelineId, _: LayerId, color: Color) {
|
||||||
match self.compositor_layer {
|
match self.compositor_layer {
|
||||||
Some(ref mut layer) => layer.unrendered_color = color,
|
Some(ref mut layer) => layer.unrendered_color = color,
|
||||||
|
|
|
@ -26,7 +26,7 @@ use servo_msg::constellation_msg::PipelineId;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(target_os="macos")]
|
#[cfg(target_os="macos")]
|
||||||
#[cfg(target_os="android")]
|
#[cfg(target_os="android")]
|
||||||
use layers::layers::VerticalFlip;
|
use layers::layers::VerticalFlip;
|
||||||
#[cfg(not(target_os="macos"))]
|
#[cfg(not(target_os="macos"))]
|
||||||
|
@ -41,7 +41,7 @@ static MAX_TILE_MEMORY_PER_LAYER: uint = 10000000;
|
||||||
/// or animation behavior. This can include absolute positioned elements, iframes, etc.
|
/// or animation behavior. This can include absolute positioned elements, iframes, etc.
|
||||||
/// Each layer can also have child layers.
|
/// Each layer can also have child layers.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): This should be merged with the concept of a layer in `rust-layers` and
|
/// FIXME(#2003, pcwalton): This should be merged with the concept of a layer in `rust-layers` and
|
||||||
/// ultimately removed, except as a set of helper methods on `rust-layers` layers.
|
/// ultimately removed, except as a set of helper methods on `rust-layers` layers.
|
||||||
pub struct CompositorLayer {
|
pub struct CompositorLayer {
|
||||||
/// This layer's pipeline. BufferRequests and mouse events will be sent through this.
|
/// This layer's pipeline. BufferRequests and mouse events will be sent through this.
|
||||||
|
@ -216,7 +216,7 @@ impl CompositorLayer {
|
||||||
unrendered_color: gfx::color::rgba(0.0, 0.0, 0.0, 0.0),
|
unrendered_color: gfx::color::rgba(0.0, 0.0, 0.0, 0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a child layer to the layer with the given ID and the given pipeline, if it doesn't
|
/// Adds a child layer to the layer with the given ID and the given pipeline, if it doesn't
|
||||||
/// exist yet. The child layer will have the same pipeline, tile size, memory limit, and CPU
|
/// exist yet. The child layer will have the same pipeline, tile size, memory limit, and CPU
|
||||||
/// painting status as its parent.
|
/// painting status as its parent.
|
||||||
|
@ -248,18 +248,18 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we've already made this child layer.
|
// See if we've already made this child layer.
|
||||||
for kid_holder in self.children.iter() {
|
if self.children.iter().any(|kid_holder| {
|
||||||
if kid_holder.child.pipeline.id == pipeline_id &&
|
kid_holder.child.pipeline.id == pipeline_id &&
|
||||||
kid_holder.child.id == child_layer_id {
|
kid_holder.child.id == child_layer_id
|
||||||
return true
|
}) {
|
||||||
}
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut kid = ~CompositorLayer::new(self.pipeline.clone(),
|
let mut kid = ~CompositorLayer::new(self.pipeline.clone(),
|
||||||
child_layer_id,
|
child_layer_id,
|
||||||
rect,
|
rect,
|
||||||
Some(page_size),
|
Some(page_size),
|
||||||
self.quadtree.tile_size(),
|
self.quadtree.tile_size(),
|
||||||
self.cpu_painting,
|
self.cpu_painting,
|
||||||
DoesntWantScrollEvents,
|
DoesntWantScrollEvents,
|
||||||
scroll_policy);
|
scroll_policy);
|
||||||
|
@ -452,8 +452,8 @@ impl CompositorLayer {
|
||||||
if !request.is_empty() {
|
if !request.is_empty() {
|
||||||
// Ask for tiles.
|
// Ask for tiles.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): We may want to batch these up in the case in which one
|
// FIXME(#2003, pcwalton): We may want to batch these up in the case in which
|
||||||
// page has multiple layers, to avoid the user seeing inconsistent states.
|
// one page has multiple layers, to avoid the user seeing inconsistent states.
|
||||||
let msg = ReRenderMsg(request, scale, self.id, self.epoch);
|
let msg = ReRenderMsg(request, scale, self.id, self.epoch);
|
||||||
self.pipeline.render_chan.try_send(msg);
|
self.pipeline.render_chan.try_send(msg);
|
||||||
}
|
}
|
||||||
|
@ -600,12 +600,9 @@ impl CompositorLayer {
|
||||||
-> bool {
|
-> bool {
|
||||||
// Search children for the right layer to move.
|
// Search children for the right layer to move.
|
||||||
if self.pipeline.id != pipeline_id || self.id != layer_id {
|
if self.pipeline.id != pipeline_id || self.id != layer_id {
|
||||||
for kid_holder in self.children.mut_iter() {
|
return self.children.mut_iter().any(|kid_holder| {
|
||||||
if kid_holder.child.move(pipeline_id, layer_id, origin, window_size) {
|
kid_holder.child.move(pipeline_id, layer_id, origin, window_size)
|
||||||
return true
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.wants_scroll_events != WantsScrollEvents {
|
if self.wants_scroll_events != WantsScrollEvents {
|
||||||
|
@ -625,7 +622,7 @@ impl CompositorLayer {
|
||||||
self.scroll_offset.x = self.scroll_offset.x.clamp(&min_x, &0.0);
|
self.scroll_offset.x = self.scroll_offset.x.clamp(&min_x, &0.0);
|
||||||
let min_y = cmp::min(window_size.height - page_size.height, 0.0);
|
let min_y = cmp::min(window_size.height - page_size.height, 0.0);
|
||||||
self.scroll_offset.y = self.scroll_offset.y.clamp(&min_y, &0.0);
|
self.scroll_offset.y = self.scroll_offset.y.clamp(&min_y, &0.0);
|
||||||
|
|
||||||
// check to see if we scrolled
|
// check to see if we scrolled
|
||||||
if old_origin - self.scroll_offset == Point2D(0f32, 0f32) {
|
if old_origin - self.scroll_offset == Point2D(0f32, 0f32) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -874,9 +871,8 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
Tree(ref mut quadtree) => quadtree,
|
Tree(ref mut quadtree) => quadtree,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut unused_tiles = ~[];
|
let mut unused_tiles = ~[];
|
||||||
// `move_rev_iter` is more efficient than `.move_iter().reverse()`.
|
|
||||||
for buffer in new_buffers.buffers.move_rev_iter() {
|
for buffer in new_buffers.buffers.move_rev_iter() {
|
||||||
unused_tiles.push_all_move(quadtree.add_tile_pixel(buffer.screen_pos.origin.x,
|
unused_tiles.push_all_move(quadtree.add_tile_pixel(buffer.screen_pos.origin.x,
|
||||||
buffer.screen_pos.origin.y,
|
buffer.screen_pos.origin.y,
|
||||||
|
@ -1013,10 +1009,7 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_of_first_child(&self) -> LayerId {
|
pub fn id_of_first_child(&self) -> LayerId {
|
||||||
for kid_holder in self.children.iter() {
|
self.children.iter().next().expect("no first child!").child.id
|
||||||
return kid_holder.child.id
|
|
||||||
}
|
|
||||||
fail!("no first child!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,13 +94,15 @@ impl RenderListener for CompositorChan {
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
metadata: ~[LayerMetadata],
|
metadata: ~[LayerMetadata],
|
||||||
epoch: Epoch) {
|
epoch: Epoch) {
|
||||||
// FIXME(pcwalton): This assumes that the first layer determines the page size, and that
|
// FIXME(#2004, pcwalton): This assumes that the first layer determines the page size, and
|
||||||
// all other layers are immediate children of it. This is sufficient to handle
|
// that all other layers are immediate children of it. This is sufficient to handle
|
||||||
// `position: fixed` but will not be sufficient to handle `overflow: scroll` or transforms.
|
// `position: fixed` but will not be sufficient to handle `overflow: scroll` or transforms.
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for metadata in metadata.iter() {
|
for metadata in metadata.iter() {
|
||||||
let origin = Point2D(metadata.rect.origin.x as f32, metadata.rect.origin.y as f32);
|
let origin = Point2D(metadata.position.origin.x as f32,
|
||||||
let size = Size2D(metadata.rect.size.width as f32, metadata.rect.size.height as f32);
|
metadata.position.origin.y as f32);
|
||||||
|
let size = Size2D(metadata.position.size.width as f32,
|
||||||
|
metadata.position.size.height as f32);
|
||||||
let rect = Rect(origin, size);
|
let rect = Rect(origin, size);
|
||||||
if first {
|
if first {
|
||||||
self.chan.send(CreateRootCompositorLayerIfNecessary(pipeline_id,
|
self.chan.send(CreateRootCompositorLayerIfNecessary(pipeline_id,
|
||||||
|
@ -115,7 +117,9 @@ impl RenderListener for CompositorChan {
|
||||||
metadata.scroll_policy));
|
metadata.scroll_policy));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.chan.send(SetUnRenderedColor(pipeline_id, metadata.id, metadata.color));
|
self.chan.send(SetUnRenderedColor(pipeline_id,
|
||||||
|
metadata.id,
|
||||||
|
metadata.background_color));
|
||||||
self.chan.send(SetLayerPageSize(pipeline_id, metadata.id, size, epoch));
|
self.chan.send(SetLayerPageSize(pipeline_id, metadata.id, size, epoch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -477,7 +477,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
|
|
||||||
// if window is outside of visible region, nothing to do
|
// if window is outside of visible region, nothing to do
|
||||||
if w_x + w_width < s_x || w_x > s_x + s_size
|
if w_x + w_width < s_x || w_x > s_x + s_size
|
||||||
|| w_y + w_height < s_y || w_y > s_y + s_size
|
|| w_y + w_height < s_y || w_y > s_y + s_size
|
||||||
|| w_x >= clip.width || w_y >= clip.height {
|
|| w_x >= clip.width || w_y >= clip.height {
|
||||||
return (~[], ~[], 0);
|
return (~[], ~[], 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,31 +27,31 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> {
|
||||||
let layout_data_ref = self.borrow_layout_data();
|
let layout_data_ref = self.borrow_layout_data();
|
||||||
match self.get_element_type() {
|
match self.get_element_type() {
|
||||||
Before | BeforeBlock => {
|
Before | BeforeBlock => {
|
||||||
return cast::transmute_region(layout_data_ref.get()
|
cast::transmute_region(layout_data_ref.get()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data
|
.data
|
||||||
.before_style
|
.before_style
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
After | AfterBlock => {
|
After | AfterBlock => {
|
||||||
return cast::transmute_region(layout_data_ref.get()
|
cast::transmute_region(layout_data_ref.get()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data
|
.data
|
||||||
.after_style
|
.after_style
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
Normal => {
|
Normal => {
|
||||||
return cast::transmute_region(layout_data_ref.get()
|
cast::transmute_region(layout_data_ref.get()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data
|
.data
|
||||||
.style
|
.style
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
//!
|
//!
|
||||||
//! CB: Containing Block of the current flow.
|
//! CB: Containing Block of the current flow.
|
||||||
|
|
||||||
use layout::box_::{Box, ImageBox, MainBoxKind, ScannedTextBox};
|
use layout::box_::{Box, ImageBox, ScannedTextBox};
|
||||||
use layout::construct::FlowConstructor;
|
use layout::construct::FlowConstructor;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, DisplayListBuildingInfo};
|
use layout::display_list_builder::{DisplayListBuilder, DisplayListBuildingInfo};
|
||||||
|
@ -459,10 +459,10 @@ pub enum MarginsMayCollapseFlag {
|
||||||
//
|
//
|
||||||
// If any fixed descendants of kids are present, this kid needs a layer.
|
// If any fixed descendants of kids are present, this kid needs a layer.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): This is too layer-happy. Like WebKit, we shouldn't do this unless
|
// FIXME(#2006, pcwalton): This is too layer-happy. Like WebKit, we shouldn't do this unless
|
||||||
// the positioned descendants are actually on top of the fixed kids.
|
// the positioned descendants are actually on top of the fixed kids.
|
||||||
//
|
//
|
||||||
// TODO(pcwalton): Do this for CSS transforms and opacity too, at least if they're
|
// TODO(#1244, #2007, pcwalton): Do this for CSS transforms and opacity too, at least if they're
|
||||||
// animating.
|
// animating.
|
||||||
fn propagate_layer_flag_from_child(layers_needed_for_descendants: &mut bool, kid: &mut Flow) {
|
fn propagate_layer_flag_from_child(layers_needed_for_descendants: &mut bool, kid: &mut Flow) {
|
||||||
if kid.is_absolute_containing_block() {
|
if kid.is_absolute_containing_block() {
|
||||||
|
@ -498,21 +498,17 @@ pub struct BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockFlow {
|
impl BlockFlow {
|
||||||
pub fn from_node(constructor: &mut FlowConstructor,
|
pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow {
|
||||||
node: &ThreadSafeLayoutNode)
|
|
||||||
-> BlockFlow {
|
|
||||||
BlockFlow {
|
BlockFlow {
|
||||||
base: BaseFlow::new((*node).clone()),
|
base: BaseFlow::new((*node).clone()),
|
||||||
box_: Some(Box::new(constructor, node, MainBoxKind)),
|
box_: Some(Box::new(constructor, node)),
|
||||||
is_root: false,
|
is_root: false,
|
||||||
static_y_offset: Au::new(0),
|
static_y_offset: Au::new(0),
|
||||||
float: None
|
float: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Box) -> BlockFlow {
|
||||||
box_: Box)
|
|
||||||
-> BlockFlow {
|
|
||||||
BlockFlow {
|
BlockFlow {
|
||||||
base: BaseFlow::new((*node).clone()),
|
base: BaseFlow::new((*node).clone()),
|
||||||
box_: Some(box_),
|
box_: Some(box_),
|
||||||
|
@ -528,7 +524,7 @@ impl BlockFlow {
|
||||||
-> BlockFlow {
|
-> BlockFlow {
|
||||||
BlockFlow {
|
BlockFlow {
|
||||||
base: BaseFlow::new((*node).clone()),
|
base: BaseFlow::new((*node).clone()),
|
||||||
box_: Some(Box::new(constructor, node, MainBoxKind)),
|
box_: Some(Box::new(constructor, node)),
|
||||||
is_root: false,
|
is_root: false,
|
||||||
static_y_offset: Au::new(0),
|
static_y_offset: Au::new(0),
|
||||||
float: Some(~FloatedBlockInfo::new(float_kind))
|
float: Some(~FloatedBlockInfo::new(float_kind))
|
||||||
|
@ -828,7 +824,7 @@ impl BlockFlow {
|
||||||
|
|
||||||
// Absolute positioning establishes a block formatting context. Don't propagate floats
|
// Absolute positioning establishes a block formatting context. Don't propagate floats
|
||||||
// in or out. (But do propagate them between kids.)
|
// in or out. (But do propagate them between kids.)
|
||||||
if inorder && (self.is_absolutely_positioned()) {
|
if inorder && self.is_absolutely_positioned() {
|
||||||
self.base.floats = Floats::new();
|
self.base.floats = Floats::new();
|
||||||
}
|
}
|
||||||
if margins_may_collapse != MarginsMayCollapse {
|
if margins_may_collapse != MarginsMayCollapse {
|
||||||
|
@ -879,7 +875,7 @@ impl BlockFlow {
|
||||||
if kid_base.clear != clear::none {
|
if kid_base.clear != clear::none {
|
||||||
// We have clearance, so assume there are no floats in and perform layout.
|
// We have clearance, so assume there are no floats in and perform layout.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): This could be wrong if we have `clear: left` or
|
// FIXME(#2008, pcwalton): This could be wrong if we have `clear: left` or
|
||||||
// `clear: right` and there are still floats to impact, of course. But this
|
// `clear: right` and there are still floats to impact, of course. But this
|
||||||
// gets complicated with margin collapse. Possibly the right thing to do is
|
// gets complicated with margin collapse. Possibly the right thing to do is
|
||||||
// to lay out the block again in this rare case. (Note that WebKit can lay
|
// to lay out the block again in this rare case. (Note that WebKit can lay
|
||||||
|
@ -899,8 +895,8 @@ impl BlockFlow {
|
||||||
|
|
||||||
floats_out = Some(flow::mut_base(kid).floats.clone());
|
floats_out = Some(flow::mut_base(kid).floats.clone());
|
||||||
|
|
||||||
// FIXME(pcwalton): A horrible hack that has to do with the fact that `origin.y`
|
// A horrible hack that has to do with the fact that `origin.y` is used for
|
||||||
// is used for something else later (containing block for float).
|
// something else later (containing block for float).
|
||||||
if kid.is_float() {
|
if kid.is_float() {
|
||||||
flow::mut_base(kid).position.origin.y = cur_y;
|
flow::mut_base(kid).position.origin.y = cur_y;
|
||||||
}
|
}
|
||||||
|
@ -972,10 +968,10 @@ impl BlockFlow {
|
||||||
translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
|
translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): The max is taken here so that you can scroll the page, but this is not
|
// FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, but this
|
||||||
// correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the root
|
// is not correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the
|
||||||
// element as having `overflow: scroll` and use the layers-based scrolling infrastructure
|
// root element as having `overflow: scroll` and use the layers-based scrolling
|
||||||
// to make it scrollable.
|
// infrastructure to make it scrollable.
|
||||||
let mut height = cur_y - top_offset;
|
let mut height = cur_y - top_offset;
|
||||||
if self.is_root() {
|
if self.is_root() {
|
||||||
height = Au::max(layout_context.screen_size.height, height)
|
height = Au::max(layout_context.screen_size.height, height)
|
||||||
|
@ -1002,7 +998,6 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
for fragment in self.box_.iter() {
|
for fragment in self.box_.iter() {
|
||||||
// FIXME(pcwalton): Is this right?
|
|
||||||
let containing_block_height = height;
|
let containing_block_height = height;
|
||||||
|
|
||||||
let mut candidate_height_iterator =
|
let mut candidate_height_iterator =
|
||||||
|
@ -1214,14 +1209,6 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process absolute descendant links.
|
// Process absolute descendant links.
|
||||||
//
|
|
||||||
// TODO: Maybe we should handle position 'absolute' and 'fixed'
|
|
||||||
// descendants before normal descendants just in case there is a
|
|
||||||
// problem when display-list building is parallel and both the
|
|
||||||
// original parent and this flow access the same absolute flow.
|
|
||||||
// Note that this can only be done once we have paint order
|
|
||||||
// working cos currently the later boxes paint over the absolute
|
|
||||||
// and fixed boxes :|
|
|
||||||
let mut absolute_info = info;
|
let mut absolute_info = info;
|
||||||
absolute_info.layers_needed_for_positioned_flows =
|
absolute_info.layers_needed_for_positioned_flows =
|
||||||
self.base.flags_info.flags.layers_needed_for_descendants();
|
self.base.flags_info.flags.layers_needed_for_descendants();
|
||||||
|
@ -1245,8 +1232,8 @@ impl BlockFlow {
|
||||||
builder: &mut DisplayListBuilder,
|
builder: &mut DisplayListBuilder,
|
||||||
info: &DisplayListBuildingInfo) {
|
info: &DisplayListBuildingInfo) {
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
// TODO(pcwalton): This is a pseudo-stacking context. We need to merge `z-index: auto`
|
// TODO(#2009, pcwalton): This is a pseudo-stacking context. We need to merge `z-index:
|
||||||
// kids into the parent stacking context, when that is supported.
|
// auto` kids into the parent stacking context, when that is supported.
|
||||||
self.build_display_list_float(stacking_context, builder, info)
|
self.build_display_list_float(stacking_context, builder, info)
|
||||||
} else if self.is_absolutely_positioned() {
|
} else if self.is_absolutely_positioned() {
|
||||||
self.build_display_list_abs(stacking_context, builder, info)
|
self.build_display_list_abs(stacking_context, builder, info)
|
||||||
|
@ -1395,14 +1382,12 @@ impl BlockFlow {
|
||||||
if !info.layers_needed_for_positioned_flows && !self.base.flags_info.flags.needs_layer() {
|
if !info.layers_needed_for_positioned_flows && !self.base.flags_info.flags.needs_layer() {
|
||||||
// We didn't need a layer.
|
// We didn't need a layer.
|
||||||
//
|
//
|
||||||
// TODO(pcwalton): `z-index`.
|
// TODO(#781, pcwalton): `z-index`.
|
||||||
parent_stacking_context.positioned_descendants.push((0, stacking_context.flatten()));
|
parent_stacking_context.positioned_descendants.push((0, stacking_context.flatten()));
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got here, then we need a new layer.
|
// If we got here, then we need a new layer.
|
||||||
//
|
|
||||||
// FIXME(pcwalton): The color is wrong!
|
|
||||||
let size = Size2D(self.base.position.size.width.to_nearest_px() as uint,
|
let size = Size2D(self.base.position.size.width.to_nearest_px() as uint,
|
||||||
self.base.position.size.height.to_nearest_px() as uint);
|
self.base.position.size.height.to_nearest_px() as uint);
|
||||||
let origin = Point2D(info.absolute_containing_block_position.x.to_nearest_px() as uint,
|
let origin = Point2D(info.absolute_containing_block_position.x.to_nearest_px() as uint,
|
||||||
|
@ -1415,8 +1400,8 @@ impl BlockFlow {
|
||||||
let new_layer = RenderLayer {
|
let new_layer = RenderLayer {
|
||||||
id: self.layer_id(0),
|
id: self.layer_id(0),
|
||||||
display_list: Arc::new(stacking_context.flatten()),
|
display_list: Arc::new(stacking_context.flatten()),
|
||||||
rect: Rect(origin, size),
|
position: Rect(origin, size),
|
||||||
color: color::rgba(255.0, 255.0, 255.0, 0.0),
|
background_color: color::rgba(255.0, 255.0, 255.0, 0.0),
|
||||||
scroll_policy: scroll_policy,
|
scroll_policy: scroll_policy,
|
||||||
};
|
};
|
||||||
builder.layers.push(new_layer)
|
builder.layers.push(new_layer)
|
||||||
|
@ -1433,6 +1418,8 @@ impl BlockFlow {
|
||||||
self.base.position.origin.y
|
self.base.position.origin.y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initializes the containing width if this block flow is a float. This is done at the start
|
||||||
|
/// of `assign_widths`.
|
||||||
fn set_containing_width_if_float(&mut self, containing_block_width: Au) {
|
fn set_containing_width_if_float(&mut self, containing_block_width: Au) {
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
self.float.get_mut_ref().containing_width = containing_block_width;
|
self.float.get_mut_ref().containing_width = containing_block_width;
|
||||||
|
@ -1442,6 +1429,7 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns the computed left content edge and width to all the children of this block flow.
|
||||||
pub fn propagate_assigned_width_to_children(&mut self,
|
pub fn propagate_assigned_width_to_children(&mut self,
|
||||||
left_content_edge: Au,
|
left_content_edge: Au,
|
||||||
content_width: Au,
|
content_width: Au,
|
||||||
|
@ -1474,7 +1462,6 @@ impl BlockFlow {
|
||||||
// This value is used only for table cells.
|
// This value is used only for table cells.
|
||||||
let mut kid_left_margin_edge = left_content_edge;
|
let mut kid_left_margin_edge = left_content_edge;
|
||||||
|
|
||||||
// FIXME(ksh8281): avoid copy
|
|
||||||
let flags_info = self.base.flags_info.clone();
|
let flags_info = self.base.flags_info.clone();
|
||||||
for (i, kid) in self.base.child_iter().enumerate() {
|
for (i, kid) in self.base.child_iter().enumerate() {
|
||||||
if kid.is_block_flow() {
|
if kid.is_block_flow() {
|
||||||
|
@ -1747,9 +1734,9 @@ impl Flow for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layer_id(&self, fragment_index: uint) -> LayerId {
|
fn layer_id(&self, fragment_index: uint) -> LayerId {
|
||||||
// FIXME(pcwalton): This is a hack and is totally bogus in the presence of pseudo-elements.
|
// FIXME(#2010, pcwalton): This is a hack and is totally bogus in the presence of pseudo-
|
||||||
// But until we have incremental reflow we can't do better--we recreate the flow for every
|
// elements. But until we have incremental reflow we can't do better--we recreate the flow
|
||||||
// DOM node so otherwise we nuke layers on every reflow.
|
// for every DOM node so otherwise we nuke layers on every reflow.
|
||||||
match self.box_ {
|
match self.box_ {
|
||||||
Some(ref box_) => {
|
Some(ref box_) => {
|
||||||
LayerId(box_.node.id(), fragment_index)
|
LayerId(box_.node.id(), fragment_index)
|
||||||
|
|
|
@ -292,8 +292,8 @@ pub enum SplitBoxResult {
|
||||||
|
|
||||||
/// Data for inline boxes.
|
/// Data for inline boxes.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): Copying `InlineParentInfo` vectors all the time is really inefficient. Use
|
/// FIXME(#2013, pcwalton): Copying `InlineParentInfo` vectors all the time is really inefficient.
|
||||||
/// atomic reference counting instead.
|
/// Use atomic reference counting instead.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct InlineInfo {
|
pub struct InlineInfo {
|
||||||
parent_info: SmallVec0<InlineParentInfo>,
|
parent_info: SmallVec0<InlineParentInfo>,
|
||||||
|
@ -418,14 +418,6 @@ def_noncontent!(bottom, noncontent_bottom, noncontent_inline_bottom)
|
||||||
def_noncontent_horiz!(left, merge_noncontent_inline_left, clear_noncontent_inline_left)
|
def_noncontent_horiz!(left, merge_noncontent_inline_left, clear_noncontent_inline_left)
|
||||||
def_noncontent_horiz!(right, merge_noncontent_inline_right, clear_noncontent_inline_right)
|
def_noncontent_horiz!(right, merge_noncontent_inline_right, clear_noncontent_inline_right)
|
||||||
|
|
||||||
/// Some DOM nodes can contribute more than one type of box. We call these boxes "sub-boxes". For
|
|
||||||
/// these nodes, this enum is used to determine which sub-box to construct for that node.
|
|
||||||
pub enum SubBoxKind {
|
|
||||||
/// The main box for this node. All DOM nodes that are rendered at all have at least a main
|
|
||||||
/// box.
|
|
||||||
MainBoxKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Box {
|
impl Box {
|
||||||
/// Constructs a new `Box` instance for the given node.
|
/// Constructs a new `Box` instance for the given node.
|
||||||
///
|
///
|
||||||
|
@ -434,13 +426,7 @@ impl Box {
|
||||||
/// * `constructor`: The flow constructor.
|
/// * `constructor`: The flow constructor.
|
||||||
///
|
///
|
||||||
/// * `node`: The node to create a box for.
|
/// * `node`: The node to create a box for.
|
||||||
///
|
pub fn new(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> Box {
|
||||||
/// * `sub_box_kind`: The kind of box to create for the node, in case this node can
|
|
||||||
/// contribute more than one type of box. See the definition of `SubBoxKind`.
|
|
||||||
pub fn new(constructor: &mut FlowConstructor,
|
|
||||||
node: &ThreadSafeLayoutNode,
|
|
||||||
sub_box_kind: SubBoxKind)
|
|
||||||
-> Box {
|
|
||||||
Box {
|
Box {
|
||||||
node: OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
node: OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
||||||
style: node.style().clone(),
|
style: node.style().clone(),
|
||||||
|
@ -448,7 +434,7 @@ impl Box {
|
||||||
border: RefCell::new(Zero::zero()),
|
border: RefCell::new(Zero::zero()),
|
||||||
padding: RefCell::new(Zero::zero()),
|
padding: RefCell::new(Zero::zero()),
|
||||||
margin: RefCell::new(Zero::zero()),
|
margin: RefCell::new(Zero::zero()),
|
||||||
specific: constructor.build_specific_box_info_for_node(node, sub_box_kind),
|
specific: constructor.build_specific_box_info_for_node(node),
|
||||||
position_offsets: RefCell::new(Zero::zero()),
|
position_offsets: RefCell::new(Zero::zero()),
|
||||||
inline_info: RefCell::new(None),
|
inline_info: RefCell::new(None),
|
||||||
new_line_pos: ~[],
|
new_line_pos: ~[],
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use layout::block::BlockFlow;
|
use layout::block::BlockFlow;
|
||||||
use layout::box_::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo};
|
use layout::box_::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo};
|
||||||
use layout::box_::{InlineInfo, InlineParentInfo, MainBoxKind, SpecificBoxInfo, SubBoxKind};
|
use layout::box_::{InlineInfo, InlineParentInfo, SpecificBoxInfo};
|
||||||
use layout::box_::{TableBox, TableCellBox, TableColumnBox, TableColumnBoxInfo, TableRowBox};
|
use layout::box_::{TableBox, TableCellBox, TableColumnBox, TableColumnBoxInfo, TableRowBox};
|
||||||
use layout::box_::{TableWrapperBox, UnscannedTextBox, UnscannedTextBoxInfo};
|
use layout::box_::{TableWrapperBox, UnscannedTextBox, UnscannedTextBoxInfo};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
@ -50,7 +50,7 @@ use gfx::font_context::FontContext;
|
||||||
use script::dom::bindings::codegen::InheritTypes::TextCast;
|
use script::dom::bindings::codegen::InheritTypes::TextCast;
|
||||||
use script::dom::bindings::js::JS;
|
use script::dom::bindings::js::JS;
|
||||||
use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
|
use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
|
||||||
use script::dom::element::{HTMLObjectElementTypeId, HTMLPseudoElementTypeId};
|
use script::dom::element::{HTMLObjectElementTypeId};
|
||||||
use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId};
|
use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId};
|
||||||
use script::dom::element::{HTMLTableElementTypeId, HTMLTableHeaderCellElementTypeId};
|
use script::dom::element::{HTMLTableElementTypeId, HTMLTableHeaderCellElementTypeId};
|
||||||
use script::dom::element::{HTMLTableRowElementTypeId, HTMLTableSectionElementTypeId};
|
use script::dom::element::{HTMLTableRowElementTypeId, HTMLTableSectionElementTypeId};
|
||||||
|
@ -281,7 +281,8 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining.
|
/// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining.
|
||||||
fn build_box_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>) -> SpecificBoxInfo {
|
fn build_box_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
|
||||||
|
-> SpecificBoxInfo {
|
||||||
match url {
|
match url {
|
||||||
None => GenericBox,
|
None => GenericBox,
|
||||||
Some(url) => {
|
Some(url) => {
|
||||||
|
@ -293,29 +294,28 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds specific `Box` info for the given node.
|
/// Builds specific `Box` info for the given node.
|
||||||
pub fn build_specific_box_info_for_node(&mut self,
|
pub fn build_specific_box_info_for_node(&mut self, node: &ThreadSafeLayoutNode)
|
||||||
node: &ThreadSafeLayoutNode,
|
|
||||||
sub_box_kind: SubBoxKind)
|
|
||||||
-> SpecificBoxInfo {
|
-> SpecificBoxInfo {
|
||||||
match node.type_id() {
|
match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLImageElementTypeId) => {
|
Some(ElementNodeTypeId(HTMLImageElementTypeId)) => {
|
||||||
self.build_box_info_for_image(node, node.image_url())
|
self.build_box_info_for_image(node, node.image_url())
|
||||||
}
|
}
|
||||||
ElementNodeTypeId(HTMLIFrameElementTypeId) => IframeBox(IframeBoxInfo::new(node)),
|
Some(ElementNodeTypeId(HTMLIFrameElementTypeId)) => {
|
||||||
ElementNodeTypeId(HTMLObjectElementTypeId) => {
|
IframeBox(IframeBoxInfo::new(node))
|
||||||
|
}
|
||||||
|
Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => {
|
||||||
let data = node.get_object_data(&self.layout_context.url);
|
let data = node.get_object_data(&self.layout_context.url);
|
||||||
self.build_box_info_for_image(node, data)
|
self.build_box_info_for_image(node, data)
|
||||||
}
|
}
|
||||||
ElementNodeTypeId(HTMLTableElementTypeId) => TableWrapperBox,
|
Some(ElementNodeTypeId(HTMLTableElementTypeId)) => TableWrapperBox,
|
||||||
ElementNodeTypeId(HTMLTableColElementTypeId) => {
|
Some(ElementNodeTypeId(HTMLTableColElementTypeId)) => {
|
||||||
TableColumnBox(TableColumnBoxInfo::new(node))
|
TableColumnBox(TableColumnBoxInfo::new(node))
|
||||||
}
|
}
|
||||||
ElementNodeTypeId(HTMLTableDataCellElementTypeId) |
|
Some(ElementNodeTypeId(HTMLTableDataCellElementTypeId)) |
|
||||||
ElementNodeTypeId(HTMLTableHeaderCellElementTypeId) => TableCellBox,
|
Some(ElementNodeTypeId(HTMLTableHeaderCellElementTypeId)) => TableCellBox,
|
||||||
ElementNodeTypeId(HTMLTableRowElementTypeId) |
|
Some(ElementNodeTypeId(HTMLTableRowElementTypeId)) |
|
||||||
ElementNodeTypeId(HTMLTableSectionElementTypeId) => TableRowBox,
|
Some(ElementNodeTypeId(HTMLTableSectionElementTypeId)) => TableRowBox,
|
||||||
ElementNodeTypeId(HTMLPseudoElementTypeId) |
|
None | Some(TextNodeTypeId) => UnscannedTextBox(UnscannedTextBoxInfo::new(node)),
|
||||||
TextNodeTypeId => UnscannedTextBox(UnscannedTextBoxInfo::new(node)),
|
|
||||||
_ => GenericBox,
|
_ => GenericBox,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,7 +489,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
if kid.get_element_type() != Normal {
|
if kid.get_element_type() != Normal {
|
||||||
self.process(&kid);
|
self.process(&kid);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.build_block_flow_using_children_construction_result(
|
self.build_block_flow_using_children_construction_result(
|
||||||
&mut flow,
|
&mut flow,
|
||||||
|
@ -676,11 +676,11 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Why does this function create a box only to throw it away???
|
// FIXME(#1999, pcwalton): Why does this function create a box only to throw it away???
|
||||||
fn set_inline_info_for_inline_child(&mut self,
|
fn set_inline_info_for_inline_child(&mut self,
|
||||||
boxes: &[&Box],
|
boxes: &[&Box],
|
||||||
parent_node: &ThreadSafeLayoutNode) {
|
parent_node: &ThreadSafeLayoutNode) {
|
||||||
let parent_box = Box::new(self, parent_node, MainBoxKind);
|
let parent_box = Box::new(self, parent_node);
|
||||||
let font_style = parent_box.font_style();
|
let font_style = parent_box.font_style();
|
||||||
let font_group = self.font_context().get_resolved_font_for_style(&font_style);
|
let font_group = self.font_context().get_resolved_font_for_style(&font_style);
|
||||||
let (font_ascent,font_descent) = font_group.borrow().with_mut( |fg| {
|
let (font_ascent,font_descent) = font_group.borrow().with_mut( |fg| {
|
||||||
|
@ -692,7 +692,8 @@ impl<'a> FlowConstructor<'a> {
|
||||||
let boxes_len = boxes.len();
|
let boxes_len = boxes.len();
|
||||||
parent_box.compute_borders(parent_box.style());
|
parent_box.compute_borders(parent_box.style());
|
||||||
|
|
||||||
// FIXME(pcwalton): I suspect that `Au(0)` is not correct for the containing block width.
|
// FIXME(#2000, pcwalton): I suspect that `Au(0)` is not correct for the containing block
|
||||||
|
// width.
|
||||||
parent_box.compute_padding(parent_box.style(), Au(0));
|
parent_box.compute_padding(parent_box.style(), Au(0));
|
||||||
|
|
||||||
for (i, box_) in boxes.iter().enumerate() {
|
for (i, box_) in boxes.iter().enumerate() {
|
||||||
|
@ -739,7 +740,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
|
|
||||||
// If this node is ignorable whitespace, bail out now.
|
// If this node is ignorable whitespace, bail out now.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): Don't do this if there's padding or borders.
|
// FIXME(#2001, pcwalton): Don't do this if there's padding or borders.
|
||||||
if node.is_ignorable_whitespace() {
|
if node.is_ignorable_whitespace() {
|
||||||
let opaque_node = OpaqueNodeMethods::from_thread_safe_layout_node(node);
|
let opaque_node = OpaqueNodeMethods::from_thread_safe_layout_node(node);
|
||||||
return ConstructionItemConstructionResult(WhitespaceConstructionItem(
|
return ConstructionItemConstructionResult(WhitespaceConstructionItem(
|
||||||
|
@ -748,7 +749,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut opt_box_accumulator = None;
|
let mut opt_box_accumulator = None;
|
||||||
opt_box_accumulator.push(Box::new(self, node, MainBoxKind));
|
opt_box_accumulator.push(Box::new(self, node));
|
||||||
|
|
||||||
let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult {
|
let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult {
|
||||||
splits: None,
|
splits: None,
|
||||||
|
@ -951,20 +952,23 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
fn process(&mut self, node: &ThreadSafeLayoutNode) -> bool {
|
fn process(&mut self, node: &ThreadSafeLayoutNode) -> bool {
|
||||||
// Get the `display` property for this node, and determine whether this node is floated.
|
// Get the `display` property for this node, and determine whether this node is floated.
|
||||||
let (display, float, positioning) = match node.type_id() {
|
let (display, float, positioning) = match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLPseudoElementTypeId) => {
|
None => {
|
||||||
|
// Pseudo-element.
|
||||||
let style = node.style().get();
|
let style = node.style().get();
|
||||||
(display::inline, style.Box.get().float, style.Box.get().position)
|
(display::inline, style.Box.get().float, style.Box.get().position)
|
||||||
}
|
}
|
||||||
ElementNodeTypeId(_) => {
|
Some(ElementNodeTypeId(_)) => {
|
||||||
let style = node.style().get();
|
let style = node.style().get();
|
||||||
(style.Box.get().display, style.Box.get().float, style.Box.get().position)
|
(style.Box.get().display, style.Box.get().float, style.Box.get().position)
|
||||||
}
|
}
|
||||||
TextNodeTypeId => (display::inline, float::none, position::static_),
|
Some(TextNodeTypeId) => (display::inline, float::none, position::static_),
|
||||||
CommentNodeTypeId |
|
Some(CommentNodeTypeId) |
|
||||||
DoctypeNodeTypeId |
|
Some(DoctypeNodeTypeId) |
|
||||||
DocumentFragmentNodeTypeId |
|
Some(DocumentFragmentNodeTypeId) |
|
||||||
DocumentNodeTypeId |
|
Some(DocumentNodeTypeId) |
|
||||||
ProcessingInstructionNodeTypeId => (display::none, float::none, position::static_),
|
Some(ProcessingInstructionNodeTypeId) => {
|
||||||
|
(display::none, float::none, position::static_)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("building flow for node: {:?} {:?}", display, float);
|
debug!("building flow for node: {:?} {:?}", display, float);
|
||||||
|
@ -1077,22 +1081,22 @@ trait NodeUtils {
|
||||||
impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
|
impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
|
||||||
fn is_replaced_content(&self) -> bool {
|
fn is_replaced_content(&self) -> bool {
|
||||||
match self.type_id() {
|
match self.type_id() {
|
||||||
TextNodeTypeId |
|
Some(TextNodeTypeId) |
|
||||||
ProcessingInstructionNodeTypeId |
|
Some(ProcessingInstructionNodeTypeId) |
|
||||||
CommentNodeTypeId |
|
Some(CommentNodeTypeId) |
|
||||||
DoctypeNodeTypeId |
|
Some(DoctypeNodeTypeId) |
|
||||||
DocumentFragmentNodeTypeId |
|
Some(DocumentFragmentNodeTypeId) |
|
||||||
DocumentNodeTypeId |
|
Some(DocumentNodeTypeId) |
|
||||||
ElementNodeTypeId(HTMLPseudoElementTypeId) |
|
None |
|
||||||
ElementNodeTypeId(HTMLImageElementTypeId) => true,
|
Some(ElementNodeTypeId(HTMLImageElementTypeId)) => true,
|
||||||
ElementNodeTypeId(HTMLObjectElementTypeId) => self.has_object_data(),
|
Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => self.has_object_data(),
|
||||||
ElementNodeTypeId(_) => false,
|
Some(ElementNodeTypeId(_)) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ignorable_whitespace(&self) -> bool {
|
fn is_ignorable_whitespace(&self) -> bool {
|
||||||
match self.type_id() {
|
match self.type_id() {
|
||||||
TextNodeTypeId => {
|
Some(TextNodeTypeId) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
let text: JS<Text> = TextCast::to(self.get_jsmanaged()).unwrap();
|
let text: JS<Text> = TextCast::to(self.get_jsmanaged()).unwrap();
|
||||||
if !is_whitespace(text.get().characterdata.data) {
|
if !is_whitespace(text.get().characterdata.data) {
|
||||||
|
@ -1141,13 +1145,18 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
|
||||||
Some(ref mut layout_data) => {
|
Some(ref mut layout_data) => {
|
||||||
match self.get_element_type() {
|
match self.get_element_type() {
|
||||||
Before | BeforeBlock => {
|
Before | BeforeBlock => {
|
||||||
return mem::replace(&mut layout_data.data.before_flow_construction_result, NoConstructionResult)
|
mem::replace(&mut layout_data.data.before_flow_construction_result,
|
||||||
},
|
NoConstructionResult)
|
||||||
|
}
|
||||||
After | AfterBlock => {
|
After | AfterBlock => {
|
||||||
return mem::replace(&mut layout_data.data.after_flow_construction_result, NoConstructionResult)
|
mem::replace(&mut layout_data.data.after_flow_construction_result,
|
||||||
},
|
NoConstructionResult)
|
||||||
Normal => { return mem::replace(&mut layout_data.data.flow_construction_result, NoConstructionResult) },
|
}
|
||||||
}
|
Normal => {
|
||||||
|
mem::replace(&mut layout_data.data.flow_construction_result,
|
||||||
|
NoConstructionResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => fail!("no layout data"),
|
None => fail!("no layout data"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1101,7 +1101,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
overflow = overflow.union(&kid_overflow)
|
overflow = overflow.union(&kid_overflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): This is wrong for `position: fixed`.
|
// FIXME(#2004, pcwalton): This is wrong for `position: fixed`.
|
||||||
for descendant_link in mut_base(self).abs_descendants.iter() {
|
for descendant_link in mut_base(self).abs_descendants.iter() {
|
||||||
match descendant_link.resolve() {
|
match descendant_link.resolve() {
|
||||||
Some(flow) => {
|
Some(flow) => {
|
||||||
|
@ -1165,7 +1165,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
self.as_table_cell().build_display_list_table_cell(stacking_context, builder, info)
|
self.as_table_cell().build_display_list_table_cell(stacking_context, builder, info)
|
||||||
}
|
}
|
||||||
TableColGroupFlowClass => {
|
TableColGroupFlowClass => {
|
||||||
// Nothing to do here, I guess? --pcwalton
|
// Nothing to do here, as column groups don't render.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1233,4 +1233,3 @@ impl MutableOwnedFlowUtils for ~Flow {
|
||||||
self_borrowed.destroy();
|
self_borrowed.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -649,8 +649,8 @@ impl LayoutTask {
|
||||||
// it with extreme prejudice.
|
// it with extreme prejudice.
|
||||||
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
|
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
|
||||||
for child in node.traverse_preorder() {
|
for child in node.traverse_preorder() {
|
||||||
if child.type_id() == ElementNodeTypeId(HTMLHtmlElementTypeId) ||
|
if child.type_id() == Some(ElementNodeTypeId(HTMLHtmlElementTypeId)) ||
|
||||||
child.type_id() == ElementNodeTypeId(HTMLBodyElementTypeId) {
|
child.type_id() == Some(ElementNodeTypeId(HTMLBodyElementTypeId)) {
|
||||||
let element_bg_color = {
|
let element_bg_color = {
|
||||||
let thread_safe_child = ThreadSafeLayoutNode::new(&child);
|
let thread_safe_child = ThreadSafeLayoutNode::new(&child);
|
||||||
thread_safe_child.style()
|
thread_safe_child.style()
|
||||||
|
@ -681,8 +681,8 @@ impl LayoutTask {
|
||||||
let render_layer = RenderLayer {
|
let render_layer = RenderLayer {
|
||||||
id: layout_root.layer_id(0),
|
id: layout_root.layer_id(0),
|
||||||
display_list: display_list.clone(),
|
display_list: display_list.clone(),
|
||||||
rect: Rect(Point2D(0u, 0u), root_size),
|
position: Rect(Point2D(0u, 0u), root_size),
|
||||||
color: color,
|
background_color: color,
|
||||||
scroll_policy: Scrollable,
|
scroll_policy: Scrollable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -83,14 +83,14 @@ pub struct MarginCollapseInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MarginCollapseInfo {
|
impl MarginCollapseInfo {
|
||||||
/// TODO(pcwalton): Remove this method once `box_` is not an `Option`.
|
/// TODO(#2012, pcwalton): Remove this method once `box_` is not an `Option`.
|
||||||
pub fn new() -> MarginCollapseInfo {
|
pub fn new() -> MarginCollapseInfo {
|
||||||
MarginCollapseInfo {
|
MarginCollapseInfo {
|
||||||
state: AccumulatingCollapsibleTopMargin,
|
state: AccumulatingCollapsibleTopMargin,
|
||||||
top_margin: AdjoiningMargins::new(),
|
top_margin: AdjoiningMargins::new(),
|
||||||
margin_in: AdjoiningMargins::new(),
|
margin_in: AdjoiningMargins::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_top_margin(&mut self,
|
pub fn initialize_top_margin(&mut self,
|
||||||
fragment: &Box,
|
fragment: &Box,
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl TableFlow {
|
||||||
|
|
||||||
/// Assign height for table flow.
|
/// Assign height for table flow.
|
||||||
///
|
///
|
||||||
/// TODO(pcwalton): This probably doesn't handle margin collapse right.
|
/// TODO(#2014, pcwalton): This probably doesn't handle margin collapse right.
|
||||||
///
|
///
|
||||||
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
||||||
/// methods
|
/// methods
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl TableCellFlow {
|
||||||
|
|
||||||
/// Assign height for table-cell flow.
|
/// Assign height for table-cell flow.
|
||||||
///
|
///
|
||||||
/// TODO(pcwalton): This doesn't handle floats right.
|
/// TODO(#2015, pcwalton): This doesn't handle floats right.
|
||||||
///
|
///
|
||||||
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
||||||
/// methods
|
/// methods
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl TableWrapperFlow {
|
||||||
|
|
||||||
/// Assign height for table-wrapper flow.
|
/// Assign height for table-wrapper flow.
|
||||||
/// `Assign height` of table-wrapper flow follows a similar process to that of block flow.
|
/// `Assign height` of table-wrapper flow follows a similar process to that of block flow.
|
||||||
///
|
///
|
||||||
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
||||||
/// methods
|
/// methods
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -116,11 +116,6 @@ impl TableWrapperFlow {
|
||||||
info: &DisplayListBuildingInfo) {
|
info: &DisplayListBuildingInfo) {
|
||||||
debug!("build_display_list_table_wrapper: same process as block flow");
|
debug!("build_display_list_table_wrapper: same process as block flow");
|
||||||
self.block_flow.build_display_list_block(stacking_context, builder, info);
|
self.block_flow.build_display_list_block(stacking_context, builder, info);
|
||||||
|
|
||||||
for kid in self.block_flow.base.child_iter() {
|
|
||||||
kid.as_table().block_flow.base.position.size.height =
|
|
||||||
self.block_flow.base.position.size.height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,8 +169,6 @@ impl Flow for TableWrapperFlow {
|
||||||
let mut left_content_edge = Au::new(0);
|
let mut left_content_edge = Au::new(0);
|
||||||
let mut content_width = containing_block_width;
|
let mut content_width = containing_block_width;
|
||||||
|
|
||||||
// self.block_flow.set_containing_width_if_float(containing_block_width);
|
|
||||||
|
|
||||||
let width_computer = TableWrapper;
|
let width_computer = TableWrapper;
|
||||||
width_computer.compute_used_width_table_wrapper(self, ctx, containing_block_width);
|
width_computer.compute_used_width_table_wrapper(self, ctx, containing_block_width);
|
||||||
|
|
||||||
|
@ -286,7 +279,6 @@ impl TableWrapper {
|
||||||
},
|
},
|
||||||
AutoLayout => {
|
AutoLayout => {
|
||||||
// Automatic table layout is calculated according to CSS 2.1 § 17.5.2.2.
|
// Automatic table layout is calculated according to CSS 2.1 § 17.5.2.2.
|
||||||
// But, this spec is not specified. Since the new spec is specified, it may be modified. See #1687.
|
|
||||||
let mut cap_min = Au(0);
|
let mut cap_min = Au(0);
|
||||||
let mut cols_min = Au(0);
|
let mut cols_min = Au(0);
|
||||||
let mut cols_max = Au(0);
|
let mut cols_max = Au(0);
|
||||||
|
@ -303,8 +295,8 @@ impl TableWrapper {
|
||||||
col_pref_widths = kid.col_pref_widths();
|
col_pref_widths = kid.col_pref_widths();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 'extra_width': difference between the calculated table width and minimum width required by all columns.
|
// 'extra_width': difference between the calculated table width and minimum width
|
||||||
// It will be distributed over the columns
|
// required by all columns. It will be distributed over the columns.
|
||||||
let (width, extra_width) = match input.computed_width {
|
let (width, extra_width) = match input.computed_width {
|
||||||
Auto => {
|
Auto => {
|
||||||
if input.available_width > geometry::max(cols_max, cap_min) {
|
if input.available_width > geometry::max(cols_max, cap_min) {
|
||||||
|
@ -337,8 +329,9 @@ impl TableWrapper {
|
||||||
// The extra width is distributed over the columns
|
// The extra width is distributed over the columns
|
||||||
if extra_width > Au(0) {
|
if extra_width > Au(0) {
|
||||||
let cell_len = table_wrapper.col_widths.len() as f64;
|
let cell_len = table_wrapper.col_widths.len() as f64;
|
||||||
table_wrapper.col_widths = col_min_widths.map(|width|
|
table_wrapper.col_widths = col_min_widths.map(|width| {
|
||||||
width + extra_width.scale_by(1.0/cell_len));
|
width + extra_width.scale_by(1.0 / cell_len)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
width
|
width
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub struct PrivateLayoutData {
|
||||||
|
|
||||||
before_flow_construction_result: ConstructionResult,
|
before_flow_construction_result: ConstructionResult,
|
||||||
|
|
||||||
after_flow_construction_result: ConstructionResult,
|
after_flow_construction_result: ConstructionResult,
|
||||||
|
|
||||||
/// Information needed during parallel traversals.
|
/// Information needed during parallel traversals.
|
||||||
parallel: DomParallelInfo,
|
parallel: DomParallelInfo,
|
||||||
|
@ -235,7 +235,7 @@ impl OpaqueNodeMethods for OpaqueNode {
|
||||||
fn from_thread_safe_layout_node(node: &ThreadSafeLayoutNode) -> OpaqueNode {
|
fn from_thread_safe_layout_node(node: &ThreadSafeLayoutNode) -> OpaqueNode {
|
||||||
unsafe {
|
unsafe {
|
||||||
let abstract_node = node.get_jsmanaged();
|
let abstract_node = node.get_jsmanaged();
|
||||||
let ptr: uintptr_t = cast::transmute(abstract_node.reflector().get_jsobject());
|
let ptr: uintptr_t = abstract_node.reflector().get_jsobject() as uint;
|
||||||
OpaqueNode(ptr)
|
OpaqueNode(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ use extra::url::Url;
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementDerived};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementDerived};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
|
||||||
use script::dom::bindings::js::JS;
|
use script::dom::bindings::js::JS;
|
||||||
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId, HTMLPseudoElementTypeId};
|
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
|
||||||
use script::dom::element::{HTMLLinkElementTypeId};
|
use script::dom::element::{HTMLLinkElementTypeId};
|
||||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
use script::dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use script::dom::htmlimageelement::HTMLImageElement;
|
use script::dom::htmlimageelement::HTMLImageElement;
|
||||||
|
@ -58,8 +58,9 @@ pub trait TLayoutNode {
|
||||||
/// Creates a new layout node with the same lifetime as this layout node.
|
/// Creates a new layout node with the same lifetime as this layout node.
|
||||||
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> Self;
|
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> Self;
|
||||||
|
|
||||||
/// Returns the type ID of this node. Fails if this node is borrowed mutably.
|
/// Returns the type ID of this node. Fails if this node is borrowed mutably. Returns `None`
|
||||||
fn type_id(&self) -> NodeTypeId;
|
/// if this is a pseudo-element; otherwise, returns `Some`.
|
||||||
|
fn type_id(&self) -> Option<NodeTypeId>;
|
||||||
|
|
||||||
/// Returns the interior of this node as a `JS`. This is highly unsafe for layout to
|
/// Returns the interior of this node as a `JS`. This is highly unsafe for layout to
|
||||||
/// call and as such is marked `unsafe`.
|
/// call and as such is marked `unsafe`.
|
||||||
|
@ -73,14 +74,14 @@ pub trait TLayoutNode {
|
||||||
|
|
||||||
fn node_is_element(&self) -> bool {
|
fn node_is_element(&self) -> bool {
|
||||||
match self.type_id() {
|
match self.type_id() {
|
||||||
ElementNodeTypeId(..) => true,
|
Some(ElementNodeTypeId(..)) => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_is_document(&self) -> bool {
|
fn node_is_document(&self) -> bool {
|
||||||
match self.type_id() {
|
match self.type_id() {
|
||||||
DocumentNodeTypeId(..) => true,
|
Some(DocumentNodeTypeId(..)) => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,17 +161,21 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
|
||||||
chain: self.chain,
|
chain: self.chain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn type_id(&self) -> NodeTypeId {
|
|
||||||
self.node.type_id()
|
fn type_id(&self) -> Option<NodeTypeId> {
|
||||||
|
Some(self.node.type_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
|
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
|
||||||
&self.node
|
&self.node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_child(&self) -> Option<LayoutNode<'ln>> {
|
fn first_child(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text(&self) -> ~str {
|
fn text(&self) -> ~str {
|
||||||
unsafe {
|
unsafe {
|
||||||
if !self.get().is_text() {
|
if !self.get().is_text() {
|
||||||
|
@ -377,12 +382,12 @@ impl<'le> TElement for LayoutElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_content(content_list: &content::T) -> ~str{
|
fn get_content(content_list: &content::T) -> ~str {
|
||||||
match *content_list {
|
match *content_list {
|
||||||
content::Content(ref value) => {
|
content::Content(ref value) => {
|
||||||
let iter = &mut value.clone().move_iter().peekable();
|
let iter = &mut value.clone().move_iter().peekable();
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some(content::StringContent(str)) => str,
|
Some(content::StringContent(content)) => content,
|
||||||
_ => ~"",
|
_ => ~"",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,29 +417,33 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
||||||
/// Creates a new layout node with the same lifetime as this layout node.
|
/// Creates a new layout node with the same lifetime as this layout node.
|
||||||
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> ThreadSafeLayoutNode<'ln> {
|
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> ThreadSafeLayoutNode<'ln> {
|
||||||
ThreadSafeLayoutNode {
|
ThreadSafeLayoutNode {
|
||||||
node: LayoutNode {
|
node: LayoutNode {
|
||||||
node: node.transmute_copy(),
|
node: node.transmute_copy(),
|
||||||
chain: self.node.chain,
|
chain: self.node.chain,
|
||||||
},
|
},
|
||||||
pseudo: Normal,
|
pseudo: Normal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_id(&self) -> NodeTypeId {
|
/// Returns `None` if this is a pseudo-element.
|
||||||
|
fn type_id(&self) -> Option<NodeTypeId> {
|
||||||
if self.pseudo == Before || self.pseudo == After {
|
if self.pseudo == Before || self.pseudo == After {
|
||||||
return ElementNodeTypeId(HTMLPseudoElementTypeId)
|
return None
|
||||||
} else {
|
}
|
||||||
return self.node.type_id()
|
|
||||||
}
|
self.node.type_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
|
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
|
||||||
self.node.get_jsmanaged()
|
self.node.get_jsmanaged()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get<'a>(&'a self) -> &'a Node { // this change.
|
unsafe fn get<'a>(&'a self) -> &'a Node { // this change.
|
||||||
cast::transmute::<*mut Node,&'a Node>(self.get_jsmanaged().unsafe_get())
|
cast::transmute::<*mut Node,&'a Node>(self.get_jsmanaged().unsafe_get())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_child(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
|
fn first_child(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
|
||||||
if self.pseudo == Before {
|
if self.pseudo == Before || self.pseudo == After {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +451,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
||||||
if self.is_block(Before) && self.pseudo == Normal {
|
if self.is_block(Before) && self.pseudo == Normal {
|
||||||
let pseudo_before_node = ThreadSafeLayoutNode::new_with_pseudo_without_self(&self.node, BeforeBlock);
|
let pseudo_before_node = ThreadSafeLayoutNode::new_with_pseudo_without_self(&self.node, BeforeBlock);
|
||||||
return Some(pseudo_before_node)
|
return Some(pseudo_before_node)
|
||||||
} else if self.pseudo == Normal || self.pseudo == BeforeBlock{
|
} else if self.pseudo == Normal || self.pseudo == BeforeBlock {
|
||||||
let pseudo_before_node = ThreadSafeLayoutNode::new_with_pseudo_without_self(&self.node, Before);
|
let pseudo_before_node = ThreadSafeLayoutNode::new_with_pseudo_without_self(&self.node, Before);
|
||||||
return Some(pseudo_before_node)
|
return Some(pseudo_before_node)
|
||||||
}
|
}
|
||||||
|
@ -452,26 +461,27 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
||||||
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text(&self) -> ~str {
|
fn text(&self) -> ~str {
|
||||||
if self.pseudo == Before || self.pseudo == After {
|
if self.pseudo == Before || self.pseudo == After {
|
||||||
let layout_data_ref = self.borrow_layout_data();
|
let layout_data_ref = self.borrow_layout_data();
|
||||||
let node_ldw = layout_data_ref.get().get_ref();
|
let node_layout_data_wrapper = layout_data_ref.get().get_ref();
|
||||||
|
|
||||||
if self.pseudo == Before {
|
if self.pseudo == Before {
|
||||||
let before_style = node_ldw.data.before_style.get_ref();
|
let before_style = node_layout_data_wrapper.data.before_style.get_ref();
|
||||||
return get_content(&before_style.get().Box.get().content)
|
return get_content(&before_style.get().Box.get().content)
|
||||||
} else {
|
} else {
|
||||||
let after_style = node_ldw.data.after_style.get_ref();
|
let after_style = node_layout_data_wrapper.data.after_style.get_ref();
|
||||||
return get_content(&after_style.get().Box.get().content)
|
return get_content(&after_style.get().Box.get().content)
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
unsafe {
|
|
||||||
if !self.get().is_text() {
|
unsafe {
|
||||||
fail!("not text!")
|
if !self.get().is_text() {
|
||||||
}
|
fail!("not text!")
|
||||||
let text: JS<Text> = self.get_jsmanaged().transmute_copy();
|
|
||||||
(*text.unsafe_get()).characterdata.data.to_str()
|
|
||||||
}
|
}
|
||||||
|
let text: JS<Text> = self.get_jsmanaged().transmute_copy();
|
||||||
|
(*text.unsafe_get()).characterdata.data.to_str()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,40 +557,36 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
|
|
||||||
pub fn is_block(&self, kind: ElementType) -> bool {
|
pub fn is_block(&self, kind: ElementType) -> bool {
|
||||||
let mut layout_data_ref = self.mutate_layout_data();
|
let mut layout_data_ref = self.mutate_layout_data();
|
||||||
let node_ldw = layout_data_ref.get().get_mut_ref();
|
let node_layout_data_wrapper = layout_data_ref.get().get_mut_ref();
|
||||||
|
|
||||||
let display = match kind {
|
let display = match kind {
|
||||||
Before | BeforeBlock => {
|
Before | BeforeBlock => {
|
||||||
let before_style = node_ldw.data.before_style.get_ref();
|
let before_style = node_layout_data_wrapper.data.before_style.get_ref();
|
||||||
before_style.get().Box.get().display
|
before_style.get().Box.get().display
|
||||||
}
|
}
|
||||||
After | AfterBlock => {
|
After | AfterBlock => {
|
||||||
let after_style = node_ldw.data.after_style.get_ref();
|
let after_style = node_layout_data_wrapper.data.after_style.get_ref();
|
||||||
after_style.get().Box.get().display
|
after_style.get().Box.get().display
|
||||||
}
|
}
|
||||||
Normal => {
|
Normal => {
|
||||||
let after_style = node_ldw.data.style.get_ref();
|
let after_style = node_layout_data_wrapper.data.style.get_ref();
|
||||||
after_style.get().Box.get().display
|
after_style.get().Box.get().display
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if display == display::block {
|
display == display::block
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_before_pseudo(&self) -> bool {
|
pub fn has_before_pseudo(&self) -> bool {
|
||||||
let ldw = self.borrow_layout_data();
|
let layout_data_wrapper = self.borrow_layout_data();
|
||||||
let ldw_ref = ldw.get().get_ref();
|
let layout_data_wrapper_ref = layout_data_wrapper.get().get_ref();
|
||||||
ldw_ref.data.before_style.is_some()
|
layout_data_wrapper_ref.data.before_style.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_after_pseudo(&self) -> bool {
|
pub fn has_after_pseudo(&self) -> bool {
|
||||||
let ldw = self.borrow_layout_data();
|
let layout_data_wrapper = self.borrow_layout_data();
|
||||||
let ldw_ref = ldw.get().get_ref();
|
let layout_data_wrapper_ref = layout_data_wrapper.get().get_ref();
|
||||||
ldw_ref.data.after_style.is_some()
|
layout_data_wrapper_ref.data.after_style.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the layout data immutably. Fails on a conflicting borrow.
|
/// Borrows the layout data immutably. Fails on a conflicting borrow.
|
||||||
|
@ -650,8 +656,8 @@ impl<'a> Iterator<ThreadSafeLayoutNode<'a>> for ThreadSafeLayoutNodeChildrenIter
|
||||||
node.next_sibling()
|
node.next_sibling()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self.current_node = None;
|
self.current_node = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl Show for LayerId {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayerId {
|
impl LayerId {
|
||||||
/// FIXME(pcwalton): This is unfortunate. Maybe remove this in the future.
|
/// FIXME(#2011, pcwalton): This is unfortunate. Maybe remove this in the future.
|
||||||
pub fn null() -> LayerId {
|
pub fn null() -> LayerId {
|
||||||
LayerId(0, 0)
|
LayerId(0, 0)
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,9 @@ pub struct LayerMetadata {
|
||||||
/// An opaque ID. This is usually the address of the flow and index of the box within it.
|
/// An opaque ID. This is usually the address of the flow and index of the box within it.
|
||||||
id: LayerId,
|
id: LayerId,
|
||||||
/// The position and size of the layer in pixels.
|
/// The position and size of the layer in pixels.
|
||||||
rect: Rect<uint>,
|
position: Rect<uint>,
|
||||||
/// The background color of the layer.
|
/// The background color of the layer.
|
||||||
color: Color,
|
background_color: Color,
|
||||||
/// The scrolling policy of this layer.
|
/// The scrolling policy of this layer.
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,6 @@ pub enum ElementTypeId {
|
||||||
HTMLParamElementTypeId,
|
HTMLParamElementTypeId,
|
||||||
HTMLPreElementTypeId,
|
HTMLPreElementTypeId,
|
||||||
HTMLProgressElementTypeId,
|
HTMLProgressElementTypeId,
|
||||||
HTMLPseudoElementTypeId,
|
|
||||||
HTMLQuoteElementTypeId,
|
HTMLQuoteElementTypeId,
|
||||||
HTMLScriptElementTypeId,
|
HTMLScriptElementTypeId,
|
||||||
HTMLSelectElementTypeId,
|
HTMLSelectElementTypeId,
|
||||||
|
|
|
@ -934,9 +934,10 @@ impl ScriptTask {
|
||||||
page.query_layout(ContentBoxQuery(node.to_trusted_node_address(), chan), port);
|
page.query_layout(ContentBoxQuery(node.to_trusted_node_address(), chan), port);
|
||||||
let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(),
|
let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(),
|
||||||
to_frac_px(rect.origin.y).to_f32().unwrap());
|
to_frac_px(rect.origin.y).to_f32().unwrap());
|
||||||
// FIXME(pcwalton): This is pretty bogus when multiple layers are involved. Really
|
// FIXME(#2003, pcwalton): This is pretty bogus when multiple layers are involved.
|
||||||
// what needs to happen is that this needs to go through layout to ask which layer
|
// Really what needs to happen is that this needs to go through layout to ask which
|
||||||
// the element belongs to, and have it send the scroll message to the compositor.
|
// layer the element belongs to, and have it send the scroll message to the
|
||||||
|
// compositor.
|
||||||
self.compositor.scroll_fragment_point(pipeline_id, LayerId::null(), point);
|
self.compositor.scroll_fragment_point(pipeline_id, LayerId::null(), point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub use servo_util::geometry::Au;
|
||||||
|
|
||||||
pub type CSSFloat = f64;
|
pub type CSSFloat = f64;
|
||||||
|
|
||||||
|
pub static DEFAULT_LINE_HEIGHT: CSSFloat = 1.14;
|
||||||
|
|
||||||
pub mod specified {
|
pub mod specified {
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
|
|
|
@ -89,9 +89,7 @@ pub mod longhands {
|
||||||
THIS_STYLE_STRUCT.longhands.append(property)
|
THIS_STYLE_STRUCT.longhands.append(property)
|
||||||
LONGHANDS.append(property)
|
LONGHANDS.append(property)
|
||||||
LONGHANDS_BY_NAME[name] = property
|
LONGHANDS_BY_NAME[name] = property
|
||||||
if derived_from not in DERIVED_LONGHANDS:
|
DERIVED_LONGHANDS.setdefault(derived_from, []).append(property)
|
||||||
DERIVED_LONGHANDS[derived_from] = []
|
|
||||||
DERIVED_LONGHANDS[derived_from].append(property)
|
|
||||||
%>
|
%>
|
||||||
pub mod ${property.ident} {
|
pub mod ${property.ident} {
|
||||||
% if not no_super:
|
% if not no_super:
|
||||||
|
@ -114,9 +112,13 @@ pub mod longhands {
|
||||||
<%def name="longhand(name, no_super=False, derived_from=None)">
|
<%def name="longhand(name, no_super=False, derived_from=None)">
|
||||||
<%self:raw_longhand name="${name}" derived_from="${derived_from}">
|
<%self:raw_longhand name="${name}" derived_from="${derived_from}">
|
||||||
${caller.body()}
|
${caller.body()}
|
||||||
pub fn parse_specified(input: &[ComponentValue], base_url: &Url)
|
pub fn parse_specified(_input: &[ComponentValue], _base_url: &Url)
|
||||||
-> Option<DeclaredValue<SpecifiedValue>> {
|
-> Option<DeclaredValue<SpecifiedValue>> {
|
||||||
parse(input, base_url).map(super::SpecifiedValue)
|
% if derived_from is None:
|
||||||
|
parse(_input, _base_url).map(super::SpecifiedValue)
|
||||||
|
% else:
|
||||||
|
None
|
||||||
|
% endif
|
||||||
}
|
}
|
||||||
</%self:raw_longhand>
|
</%self:raw_longhand>
|
||||||
</%def>
|
</%def>
|
||||||
|
@ -380,6 +382,7 @@ pub mod longhands {
|
||||||
|
|
||||||
<%self:longhand name="-servo-minimum-line-height" derived_from="line-height">
|
<%self:longhand name="-servo-minimum-line-height" derived_from="line-height">
|
||||||
use super::Au;
|
use super::Au;
|
||||||
|
use super::super::common_types::DEFAULT_LINE_HEIGHT;
|
||||||
use super::super::longhands::display;
|
use super::super::longhands::display;
|
||||||
use super::super::longhands::line_height;
|
use super::super::longhands::line_height;
|
||||||
|
|
||||||
|
@ -396,17 +399,12 @@ pub mod longhands {
|
||||||
Au(0)
|
Au(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn parse(_: &[ComponentValue], _: &Url) -> Option<SpecifiedValue> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn derive(value: line_height::computed_value::T, context: &computed::Context)
|
pub fn derive(value: line_height::computed_value::T, context: &computed::Context)
|
||||||
-> Au {
|
-> Au {
|
||||||
if context.display != display::computed_value::inline {
|
if context.display != display::computed_value::inline {
|
||||||
match value {
|
match value {
|
||||||
line_height::Normal => context.font_size.scale_by(1.14),
|
line_height::Normal => context.font_size.scale_by(DEFAULT_LINE_HEIGHT),
|
||||||
line_height::Number(percentage) => context.font_size.scale_by(percentage),
|
line_height::Number(percentage) => context.font_size.scale_by(percentage),
|
||||||
line_height::Length(length) => length,
|
line_height::Length(length) => length,
|
||||||
}
|
}
|
||||||
|
@ -573,8 +571,7 @@ pub mod longhands {
|
||||||
use super::super::common_types::specified;
|
use super::super::common_types::specified;
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub use super::super::super::common_types::computed::{LP_Length, LP_Percentage};
|
use super::super::super::common_types::computed::LengthOrPercentage;
|
||||||
pub use super::super::super::common_types::computed::{LengthOrPercentage};
|
|
||||||
|
|
||||||
#[deriving(Eq, Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub struct T {
|
pub struct T {
|
||||||
|
@ -601,11 +598,12 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
computed_value::T {
|
computed_value::T {
|
||||||
horizontal: computed_value::LP_Percentage(0.0),
|
horizontal: computed::LP_Percentage(0.0),
|
||||||
vertical: computed_value::LP_Percentage(0.0),
|
vertical: computed::LP_Percentage(0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(#1997, pcwalton): Support complete CSS2 syntax.
|
||||||
pub fn parse_horizontal_and_vertical(horiz: &ComponentValue, vert: &ComponentValue)
|
pub fn parse_horizontal_and_vertical(horiz: &ComponentValue, vert: &ComponentValue)
|
||||||
-> Option<SpecifiedValue> {
|
-> Option<SpecifiedValue> {
|
||||||
let horiz = match specified::LengthOrPercentage::parse_non_negative(horiz) {
|
let horiz = match specified::LengthOrPercentage::parse_non_negative(horiz) {
|
||||||
|
@ -625,13 +623,11 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(input: &[ComponentValue], _: &Url) -> Option<SpecifiedValue> {
|
pub fn parse(input: &[ComponentValue], _: &Url) -> Option<SpecifiedValue> {
|
||||||
let (mut horizontal, mut vertical) = (None, None);
|
let mut input_iter = input.skip_whitespace();
|
||||||
for value in input.skip_whitespace() {
|
let horizontal = input_iter.next();
|
||||||
match (horizontal, vertical) {
|
let vertical = input_iter.next();
|
||||||
(None, None) => horizontal = Some(value),
|
if input_iter.next().is_some() {
|
||||||
(Some(_), None) => vertical = Some(value),
|
return None
|
||||||
_ => return None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match (horizontal, vertical) {
|
match (horizontal, vertical) {
|
||||||
|
@ -1005,21 +1001,33 @@ pub mod shorthands {
|
||||||
for component_value in input.skip_whitespace() {
|
for component_value in input.skip_whitespace() {
|
||||||
if color.is_none() {
|
if color.is_none() {
|
||||||
match background_color::from_component_value(component_value, base_url) {
|
match background_color::from_component_value(component_value, base_url) {
|
||||||
Some(v) => { color = Some(v); any = true; continue },
|
Some(v) => {
|
||||||
|
color = Some(v);
|
||||||
|
any = true;
|
||||||
|
continue
|
||||||
|
},
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if image.is_none() {
|
if image.is_none() {
|
||||||
match background_image::from_component_value(component_value, base_url) {
|
match background_image::from_component_value(component_value, base_url) {
|
||||||
Some(v) => { image = Some(v); any = true; continue },
|
Some(v) => {
|
||||||
|
image = Some(v);
|
||||||
|
any = true;
|
||||||
|
continue
|
||||||
|
},
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if repeat.is_none() {
|
if repeat.is_none() {
|
||||||
match background_repeat::from_component_value(component_value, base_url) {
|
match background_repeat::from_component_value(component_value, base_url) {
|
||||||
Some(v) => { repeat = Some(v); any = true; continue },
|
Some(v) => {
|
||||||
|
repeat = Some(v);
|
||||||
|
any = true;
|
||||||
|
continue
|
||||||
|
},
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1027,7 +1035,11 @@ pub mod shorthands {
|
||||||
if attachment.is_none() {
|
if attachment.is_none() {
|
||||||
match background_attachment::from_component_value(component_value,
|
match background_attachment::from_component_value(component_value,
|
||||||
base_url) {
|
base_url) {
|
||||||
Some(v) => { attachment = Some(v); any = true; continue },
|
Some(v) => {
|
||||||
|
attachment = Some(v);
|
||||||
|
any = true;
|
||||||
|
continue
|
||||||
|
},
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1050,11 @@ pub mod shorthands {
|
||||||
match background_position::parse_horizontal_and_vertical(
|
match background_position::parse_horizontal_and_vertical(
|
||||||
saved_component_value,
|
saved_component_value,
|
||||||
component_value) {
|
component_value) {
|
||||||
Some(v) => { position = Some(v); any = true; continue },
|
Some(v) => {
|
||||||
|
position = Some(v);
|
||||||
|
any = true;
|
||||||
|
continue
|
||||||
|
},
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1052,7 +1068,7 @@ pub mod shorthands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if any && last_component_value.is_none() {
|
if any && last_component_value.is_none() {
|
||||||
Some(Longhands {
|
Some(Longhands {
|
||||||
background_color: color,
|
background_color: color,
|
||||||
|
|
|
@ -61,8 +61,12 @@ pub trait SmallVec<T> : SmallVecPrivate<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mut_iter<'a>(&'a mut self) -> SmallVecMutIterator<'a,T> {
|
fn mut_iter<'a>(&'a mut self) -> SmallVecMutIterator<'a,T> {
|
||||||
SmallVecMutIterator {
|
unsafe {
|
||||||
iter: self.iter(),
|
SmallVecMutIterator {
|
||||||
|
ptr: cast::transmute(self.begin()),
|
||||||
|
end: cast::transmute(self.end()),
|
||||||
|
lifetime: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,17 +211,25 @@ impl<'a,T> Iterator<&'a T> for SmallVecIterator<'a,T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SmallVecMutIterator<'a,T> {
|
pub struct SmallVecMutIterator<'a,T> {
|
||||||
priv iter: SmallVecIterator<'a,T>,
|
priv ptr: *mut T,
|
||||||
|
priv end: *mut T,
|
||||||
|
priv lifetime: Option<&'a mut T>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a,T> Iterator<&'a mut T> for SmallVecMutIterator<'a,T> {
|
impl<'a,T> Iterator<&'a mut T> for SmallVecMutIterator<'a,T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<&'a mut T> {
|
fn next(&mut self) -> Option<&'a mut T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.iter.next() {
|
if self.ptr == self.end {
|
||||||
None => None,
|
return None
|
||||||
Some(reference) => Some(cast::transmute::<&'a T,&'a mut T>(reference)),
|
|
||||||
}
|
}
|
||||||
|
let old = self.ptr;
|
||||||
|
self.ptr = if mem::size_of::<T>() == 0 {
|
||||||
|
cast::transmute(self.ptr as uint + 1)
|
||||||
|
} else {
|
||||||
|
self.ptr.offset(1)
|
||||||
|
};
|
||||||
|
Some(cast::transmute(old))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit aa3e649a68b6622a26d45c78023a717d76ff369b
|
Subproject commit 10b1cf8e35fa1757bcab11dcc284f77e4ceeaffc
|
Loading…
Add table
Add a link
Reference in a new issue