aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/layout/block.rs45
-rw-r--r--src/components/main/layout/box.rs81
-rw-r--r--src/components/main/layout/construct.rs6
-rw-r--r--src/components/main/layout/context.rs11
-rw-r--r--src/components/main/layout/inline.rs21
-rw-r--r--src/components/main/layout/layout_task.rs1
-rw-r--r--src/components/script/dom/htmliframeelement.rs12
-rw-r--r--src/components/script/html/hubbub_html_parser.rs7
-rw-r--r--src/components/script/script_task.rs8
9 files changed, 114 insertions, 78 deletions
diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs
index 6da6e8fcfb0..7171887378e 100644
--- a/src/components/main/layout/block.rs
+++ b/src/components/main/layout/block.rs
@@ -13,9 +13,9 @@ use layout::model::{MaybeAuto, Specified, Auto, specified_or_none, specified};
use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType};
use std::cell::Cell;
-use geom::{Point2D, Rect, SideOffsets2D, Size2D};
+use geom::{Point2D, Rect, SideOffsets2D};
use gfx::display_list::DisplayList;
-use servo_util::geometry::{Au, to_frac_px};
+use servo_util::geometry::Au;
use servo_util::geometry;
/// Information specific to floated blocks.
@@ -58,7 +58,7 @@ pub struct BlockFlow {
/// Whether this block flow is the root flow.
is_root: bool,
- // Additional floating flow members.
+ /// Additional floating flow members.
float: Option<~FloatedBlockInfo>
}
@@ -471,27 +471,6 @@ impl BlockFlow {
return self.build_display_list_float(builder, dirty, list);
}
- if self.base.node.is_iframe_element() {
- let x = self.base.abs_position.x + do self.box.as_ref().map_default(Au::new(0)) |box| {
- box.margin.get().left + box.border.get().left + box.padding.get().left
- };
- let y = self.base.abs_position.y + do self.box.as_ref().map_default(Au::new(0)) |box| {
- box.margin.get().top + box.border.get().top + box.padding.get().top
- };
- let w = self.base.position.size.width - do self.box.as_ref().map_default(Au::new(0)) |box| {
- box.noncontent_width()
- };
- let h = self.base.position.size.height - do self.box.as_ref().map_default(Au::new(0)) |box| {
- box.noncontent_height()
- };
- do self.base.node.with_mut_iframe_element |iframe_element| {
- iframe_element.size.get_mut_ref().set_rect(Rect(Point2D(to_frac_px(x) as f32,
- to_frac_px(y) as f32),
- Size2D(to_frac_px(w) as f32,
- to_frac_px(h) as f32)));
- }
- }
-
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) {
return true;
@@ -514,21 +493,17 @@ impl BlockFlow {
false
}
- pub fn build_display_list_float<E:ExtraDisplayListData>(&mut self,
- builder: &DisplayListBuilder,
- dirty: &Rect<Au>,
- list: &Cell<DisplayList<E>>)
- -> bool {
- //TODO: implement iframe size messaging
- if self.base.node.is_iframe_element() {
- error!("float iframe size messaging not implemented yet");
- }
+ pub fn build_display_list_float<E:ExtraDisplayListData>(
+ &mut self,
+ builder: &DisplayListBuilder,
+ dirty: &Rect<Au>,
+ list: &Cell<DisplayList<E>>)
+ -> bool {
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) {
- return true;
+ return true
}
-
let offset = self.base.abs_position + self.float.get_ref().rel_pos;
// add box that starts block context
for box in self.box.iter() {
diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs
index 294098bed20..30f3b452e02 100644
--- a/src/components/main/layout/box.rs
+++ b/src/components/main/layout/box.rs
@@ -16,9 +16,11 @@ use gfx::display_list::{ClipDisplayItemClass};
use gfx::font::{FontStyle, FontWeight300};
use gfx::text::text_run::TextRun;
use script::dom::node::{AbstractNode, LayoutView};
+use servo_msg::constellation_msg::{FrameRectMsg, PipelineId, SubpageId};
use servo_net::image::holder::ImageHolder;
use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::Au;
+use servo_util::geometry;
use servo_util::range::*;
use servo_util::slot::Slot;
use servo_util::tree::{TreeNodeRef, ElementLike};
@@ -32,6 +34,7 @@ use style::computed_values::{border_style, clear, font_family, font_style, line_
use style::computed_values::{text_align, text_decoration, vertical_align, visibility};
use css::node_style::StyledNode;
+use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor};
use layout::float_context::{ClearType, ClearLeft, ClearRight, ClearBoth};
use layout::flow::Flow;
@@ -89,6 +92,7 @@ pub struct Box {
pub enum SpecificBoxInfo {
GenericBox,
ImageBox(ImageBoxInfo),
+ IframeBox(IframeBoxInfo),
ScannedTextBox(ScannedTextBoxInfo),
UnscannedTextBox(UnscannedTextBoxInfo),
}
@@ -146,6 +150,29 @@ impl ImageBoxInfo {
}
}
+/// A box that represents an inline frame (iframe). This stores the pipeline ID so that the size
+/// of this iframe can be communicated via the constellation to the iframe's own layout task.
+#[deriving(Clone)]
+pub struct IframeBoxInfo {
+ /// The pipeline ID of this iframe.
+ pipeline_id: PipelineId,
+ /// The subpage ID of this iframe.
+ subpage_id: SubpageId,
+}
+
+impl IframeBoxInfo {
+ /// Creates the information specific to an iframe box.
+ pub fn new(node: &AbstractNode<LayoutView>) -> IframeBoxInfo {
+ node.with_imm_iframe_element(|iframe_element| {
+ let size = iframe_element.size.unwrap();
+ IframeBoxInfo {
+ pipeline_id: size.pipeline_id,
+ subpage_id: size.subpage_id,
+ }
+ })
+ }
+}
+
/// A scanned text box represents a single run of text with a distinct style. A `TextBox` may be
/// split into two or more boxes across line breaks. Several `TextBox`es may correspond to a single
/// DOM text node. Split text boxes are implemented by referring to subsets of a single `TextRun`
@@ -540,7 +567,7 @@ impl Box {
/// Appendix E. Finally, the builder flattens the list.
pub fn build_display_list<E:ExtraDisplayListData>(
&self,
- _: &DisplayListBuilder,
+ builder: &DisplayListBuilder,
dirty: &Rect<Au>,
offset: Point2D<Au>,
flow: &Flow,
@@ -652,7 +679,7 @@ impl Box {
()
});
},
- GenericBox => {
+ GenericBox | IframeBox(_) => {
do list.with_mut_ref |list| {
let item = ~ClipDisplayItem {
base: BaseDisplayItem {
@@ -726,6 +753,23 @@ impl Box {
}
}
+ // If this is an iframe, then send its position and size up to the constellation.
+ //
+ // FIXME(pcwalton): Doing this during display list construction seems potentially
+ // problematic if iframes are outside the area we're computing the display list for, since
+ // they won't be able to reflow at all until the user scrolls to them. Perhaps we should
+ // separate this into two parts: first we should send the size only to the constellation
+ // once that's computed during assign-heights, and second we should should send the origin
+ // to the constellation here during display list construction. This should work because
+ // layout for the iframe only needs to know size, and origin is only relevant if the
+ // iframe is actually going to be displayed.
+ match self.specific {
+ IframeBox(ref iframe_box) => {
+ self.finalize_position_and_size_of_iframe(iframe_box, offset, builder.ctx)
+ }
+ GenericBox | ImageBox(_) | ScannedTextBox(_) | UnscannedTextBox(_) => {}
+ }
+
// Add a border, if applicable.
//
// TODO: Outlines.
@@ -736,7 +780,7 @@ impl Box {
pub fn minimum_and_preferred_widths(&self) -> (Au, Au) {
let guessed_width = self.guess_width();
let (additional_minimum, additional_preferred) = match self.specific {
- GenericBox => (Au(0), Au(0)),
+ GenericBox | IframeBox(_) => (Au(0), Au(0)),
ImageBox(ref image_box_info) => {
let image_width = image_box_info.image_width();
(image_width, image_width)
@@ -764,7 +808,7 @@ impl Box {
/// FIXME(pcwalton): This function *mutates* the height? Gross! Refactor please.
pub fn box_height(&self) -> Au {
match self.specific {
- GenericBox => Au(0),
+ GenericBox | IframeBox(_) => Au(0),
ImageBox(ref image_box_info) => {
let size = image_box_info.image.mutate().ptr.get_size();
let height = Au::from_px(size.unwrap_or(Size2D(0, 0)).height);
@@ -789,7 +833,7 @@ impl Box {
/// Attempts to split this box so that its width is no more than `max_width`.
pub fn split_to_width(&self, max_width: Au, starts_line: bool) -> SplitBoxResult {
match self.specific {
- GenericBox | ImageBox(_) => CannotSplit,
+ GenericBox | IframeBox(_) | ImageBox(_) => CannotSplit,
UnscannedTextBox(_) => fail!("Unscanned text boxes should have been scanned by now!"),
ScannedTextBox(ref text_box_info) => {
let mut pieces_processed_count: uint = 0;
@@ -899,7 +943,7 @@ impl Box {
/// Assigns the appropriate width to this box.
pub fn assign_width(&self) {
match self.specific {
- GenericBox => {
+ GenericBox | IframeBox(_) => {
// FIXME(pcwalton): This seems clownshoes; can we remove?
self.position.mutate().ptr.size.width = Au::from_px(45)
}
@@ -942,6 +986,7 @@ impl Box {
pub fn debug_str(&self) -> ~str {
let class_name = match self.specific {
GenericBox => "GenericBox",
+ IframeBox(_) => "IframeBox",
ImageBox(_) => "ImageBox",
ScannedTextBox(_) => "ScannedTextBox",
UnscannedTextBox(_) => "UnscannedTextBox",
@@ -968,5 +1013,29 @@ impl Box {
*value.bottom,
*value.left)
}
+
+ /// Sends the size and position of this iframe box to the constellation. This is out of line to
+ /// guide inlining.
+ #[inline(never)]
+ fn finalize_position_and_size_of_iframe(&self,
+ iframe_box: &IframeBoxInfo,
+ offset: Point2D<Au>,
+ layout_context: &LayoutContext) {
+ let left = offset.x + self.margin.get().left + self.border.get().left +
+ self.padding.get().left;
+ let top = offset.y + self.margin.get().top + self.border.get().top +
+ self.padding.get().top;
+ let width = self.position.get().size.width - self.noncontent_width();
+ let height = self.position.get().size.height - self.noncontent_height();
+ let origin = Point2D(geometry::to_frac_px(left) as f32, geometry::to_frac_px(top) as f32);
+ let size = Size2D(geometry::to_frac_px(width) as f32, geometry::to_frac_px(height) as f32);
+ let rect = Rect(origin, size);
+
+ debug!("finalizing position and size of iframe for {:?},{:?}",
+ iframe_box.pipeline_id,
+ iframe_box.subpage_id);
+ let msg = FrameRectMsg(iframe_box.pipeline_id, iframe_box.subpage_id, rect);
+ layout_context.constellation_chan.send(msg)
+ }
}
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs
index c7821355abe..03ab5f4033f 100644
--- a/src/components/main/layout/construct.rs
+++ b/src/components/main/layout/construct.rs
@@ -22,7 +22,8 @@
use css::node_style::StyledNode;
use layout::block::BlockFlow;
-use layout::box::{Box, GenericBox, ImageBox, ImageBoxInfo, UnscannedTextBox, UnscannedTextBoxInfo};
+use layout::box::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo};
+use layout::box::{UnscannedTextBox, UnscannedTextBoxInfo};
use layout::context::LayoutContext;
use layout::float_context::FloatType;
use layout::flow::{Flow, FlowData, MutableFlowUtils};
@@ -30,7 +31,7 @@ use layout::inline::InlineFlow;
use layout::text::TextRunScanner;
use layout::util::LayoutDataAccess;
-use script::dom::element::HTMLImageElementTypeId;
+use script::dom::element::{HTMLIframeElementTypeId, HTMLImageElementTypeId};
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
use script::dom::node::{DocumentFragmentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId};
use script::dom::node::{LayoutView, PostorderNodeMutTraversal, TextNodeTypeId};
@@ -223,6 +224,7 @@ impl<'self> FlowConstructor<'self> {
Some(image_box_info) => ImageBox(image_box_info),
}
}
+ ElementNodeTypeId(HTMLIframeElementTypeId) => IframeBox(IframeBoxInfo::new(&node)),
TextNodeTypeId => UnscannedTextBox(UnscannedTextBoxInfo::new(&node)),
_ => GenericBox,
};
diff --git a/src/components/main/layout/context.rs b/src/components/main/layout/context.rs
index 2eaa7eafc8c..42568fde501 100644
--- a/src/components/main/layout/context.rs
+++ b/src/components/main/layout/context.rs
@@ -4,16 +4,19 @@
//! Data needed by the layout task.
+use extra::arc::MutexArc;
use geom::rect::Rect;
use gfx::font_context::FontContext;
-use servo_util::geometry::Au;
+use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
-
-use extra::arc::MutexArc;
+use servo_util::geometry::Au;
/// Data needed by the layout task.
pub struct LayoutContext {
font_ctx: ~FontContext,
image_cache: MutexArc<LocalImageCache>,
- screen_size: Rect<Au>
+ screen_size: Rect<Au>,
+
+ /// A channel up to the constellation.
+ constellation_chan: ConstellationChan,
}
diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs
index 861fa93a1c9..17603d7e52f 100644
--- a/src/components/main/layout/inline.rs
+++ b/src/components/main/layout/inline.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use css::node_style::StyledNode;
-use layout::box::{Box, CannotSplit, GenericBox, ImageBox, ScannedTextBox, SplitDidFit};
+use layout::box::{Box, CannotSplit, GenericBox, IframeBox, ImageBox, ScannedTextBox, SplitDidFit};
use layout::box::{SplitDidNotFit, UnscannedTextBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
@@ -474,17 +474,12 @@ impl InlineFlow {
self.boxes = ~[];
}
- pub fn build_display_list_inline<E:ExtraDisplayListData>(&self,
- builder: &DisplayListBuilder,
- dirty: &Rect<Au>,
- list: &Cell<DisplayList<E>>)
- -> bool {
-
- //TODO: implement inline iframe size messaging
- if self.base.node.is_iframe_element() {
- error!("inline iframe size messaging not implemented yet");
- }
-
+ pub fn build_display_list_inline<E:ExtraDisplayListData>(
+ &self,
+ builder: &DisplayListBuilder,
+ dirty: &Rect<Au>,
+ list: &Cell<DisplayList<E>>)
+ -> bool {
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) {
return true;
@@ -766,7 +761,7 @@ impl Flow for InlineFlow {
(text_offset, line_height - text_offset, text_ascent)
},
- GenericBox => {
+ GenericBox | IframeBox(_) => {
let height = cur_box.position.get().size.height;
(height, Au::new(0), height)
},
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index ec82722afa0..fa813b3b8c4 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -269,6 +269,7 @@ impl LayoutTask {
image_cache: image_cache,
font_ctx: font_ctx,
screen_size: Rect(Point2D(Au(0), Au(0)), screen_size),
+ constellation_chan: self.constellation_chan.clone(),
}
}
diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs
index 7f39cfa58d8..3f8ff80a5c7 100644
--- a/src/components/script/dom/htmliframeelement.rs
+++ b/src/components/script/dom/htmliframeelement.rs
@@ -11,8 +11,7 @@ use dom::node::{AbstractNode, Node, ScriptView};
use dom::windowproxy::WindowProxy;
use extra::url::Url;
-use geom::rect::Rect;
-use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
+use servo_msg::constellation_msg::{PipelineId, SubpageId};
use std::ascii::StrAsciiExt;
enum SandboxAllowance {
@@ -32,16 +31,9 @@ pub struct HTMLIFrameElement {
sandbox: Option<u8>
}
-struct IFrameSize {
+pub struct IFrameSize {
pipeline_id: PipelineId,
subpage_id: SubpageId,
- constellation_chan: ConstellationChan,
-}
-
-impl IFrameSize {
- pub fn set_rect(&mut self, rect: Rect<f32>) {
- self.constellation_chan.send(FrameRectMsg(self.pipeline_id, self.subpage_id, rect));
- }
}
impl HTMLIFrameElement {
diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs
index e73d1205950..6ca31770032 100644
--- a/src/components/script/html/hubbub_html_parser.rs
+++ b/src/components/script/html/hubbub_html_parser.rs
@@ -17,7 +17,7 @@ use script_task::page_from_context;
use extra::url::Url;
use hubbub::hubbub;
use js::jsapi::JSContext;
-use servo_msg::constellation_msg::{ConstellationChan, SubpageId};
+use servo_msg::constellation_msg::SubpageId;
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource};
use servo_util::tree::{TreeNodeRef, ElementLike};
@@ -248,8 +248,8 @@ pub fn parse_html(cx: *JSContext,
url: Url,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
- next_subpage_id: SubpageId,
- constellation_chan: ConstellationChan) -> HtmlParserResult {
+ next_subpage_id: SubpageId)
+ -> HtmlParserResult {
debug!("Hubbub: parsing {:?}", url);
// Spawn a CSS parser to receive links to CSS style sheets.
let resource_task2 = resource_task.clone();
@@ -385,7 +385,6 @@ pub fn parse_html(cx: *JSContext,
iframe_element.size = Some(IFrameSize {
pipeline_id: pipeline_id,
subpage_id: subpage_id,
- constellation_chan: constellation_chan.clone(),
});
iframe_chan.send(HtmlDiscoveredIFrame((iframe_url,
subpage_id,
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index 4676639a6a4..226a5af6305 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -723,11 +723,11 @@ impl ScriptTask {
url.clone(),
self.resource_task.clone(),
self.image_cache_task.clone(),
- page.next_subpage_id.clone(),
- self.constellation_chan.clone());
+ page.next_subpage_id.clone());
-
- let HtmlParserResult {discovery_port} = html_parsing_result;
+ let HtmlParserResult {
+ discovery_port
+ } = html_parsing_result;
// Create the root frame.
page.frame = Some(Frame {