diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/gfx/display_list.rs | 13 | ||||
-rw-r--r-- | src/components/main/layout/block.rs | 64 | ||||
-rw-r--r-- | src/components/main/layout/box.rs | 88 | ||||
-rw-r--r-- | src/components/main/layout/construct.rs | 18 | ||||
-rw-r--r-- | src/components/main/layout/display_list_builder.rs | 6 | ||||
-rw-r--r-- | src/components/main/layout/inline.rs | 86 | ||||
-rw-r--r-- | src/components/main/layout/text.rs | 34 | ||||
-rw-r--r-- | src/components/main/layout/util.rs | 2 | ||||
-rw-r--r-- | src/components/net/image/holder.rs | 3 |
9 files changed, 156 insertions, 158 deletions
diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs index 440659c84d8..a477bc71a5d 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list.rs @@ -93,7 +93,7 @@ pub struct SolidColorDisplayItem<E> { /// Renders text. pub struct TextDisplayItem<E> { base: BaseDisplayItem<E>, - text_run: ~TextRun, + text_run: Arc<~TextRun>, range: Range, color: Color, } @@ -163,7 +163,8 @@ impl<E> DisplayItem<E> { debug!("Drawing text at {:?}.", text.base.bounds); // FIXME(pcwalton): Allocating? Why? - let font = render_context.font_ctx.get_font_by_descriptor(&text.text_run.font_descriptor).unwrap(); + let text_run = text.text_run.get(); + let font = render_context.font_ctx.get_font_by_descriptor(&text_run.font_descriptor).unwrap(); let font_metrics = font.with_borrow( |font| { font.metrics.clone() @@ -172,7 +173,7 @@ impl<E> DisplayItem<E> { let baseline_origin = Point2D(origin.x, origin.y + font_metrics.ascent); font.with_mut_borrow( |font| { font.draw_text_into_context(render_context, - &text.text_run, + text.text_run.get(), &text.range, baseline_origin, text.color); @@ -183,18 +184,18 @@ impl<E> DisplayItem<E> { let strikeout_size = font_metrics.strikeout_size; let strikeout_offset = font_metrics.strikeout_offset; - if text.text_run.decoration.underline { + if text_run.decoration.underline { let underline_y = baseline_origin.y - underline_offset; let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y), Size2D(width, underline_size)); render_context.draw_solid_color(&underline_bounds, text.color); } - if text.text_run.decoration.overline { + if text_run.decoration.overline { let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y), Size2D(width, underline_size)); render_context.draw_solid_color(&overline_bounds, text.color); } - if text.text_run.decoration.line_through { + if text_run.decoration.line_through { let strikeout_y = baseline_origin.y - strikeout_offset; let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y), Size2D(width, strikeout_size)); diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index d6b54596e4d..8c50e8b048d 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -53,7 +53,7 @@ pub struct BlockFlow { base: FlowData, /// The associated box. - box: Option<@Box>, + box: Option<~Box>, /// Whether this block flow is the root flow. is_root: bool, @@ -72,7 +72,7 @@ impl BlockFlow { } } - pub fn from_box(base: FlowData, box: @Box) -> BlockFlow { + pub fn from_box(base: FlowData, box: ~Box) -> BlockFlow { BlockFlow { base: base, box: Some(box), @@ -81,7 +81,7 @@ impl BlockFlow { } } - pub fn float_from_box(base: FlowData, float_type: FloatType, box: @Box) -> BlockFlow { + pub fn float_from_box(base: FlowData, float_type: FloatType, box: ~Box) -> BlockFlow { BlockFlow { base: base, box: Some(box), @@ -123,9 +123,9 @@ impl BlockFlow { /// Computes left and right margins and width based on CSS 2.1 section 10.3.3. /// Requires borders and padding to already be computed. fn compute_horiz(&self, - width: MaybeAuto, - left_margin: MaybeAuto, - right_margin: MaybeAuto, + width: MaybeAuto, + left_margin: MaybeAuto, + right_margin: MaybeAuto, available_width: Au) -> (Au, Au, Au) { // If width is not 'auto', and width + margins > available_width, all 'auto' margins are @@ -135,7 +135,7 @@ impl BlockFlow { Specified(width) => { let left = left_margin.specified_or_zero(); let right = right_margin.specified_or_zero(); - + if((left + right + width) > available_width) { (Specified(left), Specified(right)) } else { @@ -147,7 +147,7 @@ impl BlockFlow { //Invariant: left_margin_Au + width_Au + right_margin_Au == available_width let (left_margin_Au, width_Au, right_margin_Au) = match (left_margin, width, right_margin) { //If all have a computed value other than 'auto', the system is over-constrained and we need to discard a margin. - //if direction is ltr, ignore the specified right margin and solve for it. If it is rtl, ignore the specified + //if direction is ltr, ignore the specified right margin and solve for it. If it is rtl, ignore the specified //left margin. FIXME(eatkinson): this assumes the direction is ltr (Specified(margin_l), Specified(width), Specified(_margin_r)) => (margin_l, width, available_width - (margin_l + width )), @@ -172,7 +172,7 @@ impl BlockFlow { (width_Au, left_margin_Au, right_margin_Au) } - fn compute_block_margins(&self, box: @Box, remaining_width: Au, available_width: Au) + fn compute_block_margins(&self, box: &Box, remaining_width: Au, available_width: Au) -> (Au, Au, Au) { let style = box.style(); @@ -215,7 +215,7 @@ impl BlockFlow { return (width, margin_left, margin_right); } - fn compute_float_margins(&self, box: @Box, remaining_width: Au) -> (Au, Au, Au) { + fn compute_float_margins(&self, box: &Box, remaining_width: Au) -> (Au, Au, Au) { let style = box.style(); let margin_left = MaybeAuto::from_style(style.Margin.margin_left, remaining_width).specified_or_zero(); @@ -240,7 +240,7 @@ impl BlockFlow { let mut left_offset = Au::new(0); let mut float_ctx = Invalid; - for &box in self.box.iter() { + for box in self.box.iter() { clearance = match box.clear() { None => Au::new(0), Some(clear) => { @@ -279,7 +279,7 @@ impl BlockFlow { let mut top_margin_collapsible = false; let mut bottom_margin_collapsible = false; let mut first_in_flow = true; - for &box in self.box.iter() { + for box in self.box.iter() { if !self.is_root && box.border.get().top == Au(0) && box.padding.get().top == Au(0) { collapsible = box.margin.get().top; top_margin_collapsible = true; @@ -316,7 +316,7 @@ impl BlockFlow { } else { Au::new(0) }; - + // TODO: A box's own margins collapse if the 'min-height' property is zero, and it has neither // top or bottom borders nor top or bottom padding, and it has a 'height' of either 0 or 'auto', // and it does not contain a line box, and all of its in-flow children's margins (if any) collapse. @@ -328,7 +328,7 @@ impl BlockFlow { cur_y - top_offset - collapsing }; - for &box in self.box.iter() { + for box in self.box.iter() { let style = box.style(); height = match MaybeAuto::from_style(style.Box.height, Au::new(0)) { Auto => height, @@ -360,7 +360,7 @@ impl BlockFlow { self.base.position.size.height = height + noncontent_height; if inorder { - let extra_height = height - (cur_y - top_offset) + bottom_offset; + let extra_height = height - (cur_y - top_offset) + bottom_offset; self.base.floats_out = float_ctx.translate(Point2D(left_offset, -extra_height)); } else { self.base.floats_out = self.base.floats_in.clone(); @@ -419,7 +419,7 @@ impl BlockFlow { let mut cur_y = Au(0); let mut top_offset = Au(0); - for &box in self.box.iter() { + for box in self.box.iter() { top_offset = box.margin.get().top + box.border.get().top + box.padding.get().top; cur_y = cur_y + top_offset; } @@ -441,7 +441,7 @@ impl BlockFlow { noncontent_height = box.padding.get().top + box.padding.get().bottom + box.border.get().top + box.border.get().bottom; - + //TODO(eatkinson): compute heights properly using the 'height' property. let height_prop = MaybeAuto::from_style(box.style().Box.height, Au::new(0)).specified_or_zero(); @@ -456,24 +456,24 @@ impl BlockFlow { pub fn build_display_list_block<E:ExtraDisplayListData>( &mut self, builder: &DisplayListBuilder, - dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + dirty: &Rect<Au>, + list: &Cell<DisplayList<E>>) -> bool { if self.is_float() { 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.map_default(Au::new(0)) |box| { + 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.map_default(Au::new(0)) |box| { + 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.map_default(Au::new(0)) |box| { + 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.map_default(Au::new(0)) |box| { + 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| { @@ -508,8 +508,8 @@ impl BlockFlow { pub fn build_display_list_float<E:ExtraDisplayListData>(&mut self, builder: &DisplayListBuilder, - dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + dirty: &Rect<Au>, + list: &Cell<DisplayList<E>>) -> bool { //TODO: implement iframe size messaging if self.base.node.is_iframe_element() { @@ -627,7 +627,7 @@ impl Flow for BlockFlow { self.base.is_inorder = false; } - for &box in self.box.iter() { + for box in self.box.iter() { let style = box.style(); // Can compute padding here since we know containing block width. @@ -643,9 +643,9 @@ impl Flow for BlockFlow { remaining_width).specified_or_zero(); let (width, margin_left, margin_right) = if self.is_float() { - self.compute_float_margins(box, remaining_width) + self.compute_float_margins(*box, remaining_width) } else { - self.compute_block_margins(box, remaining_width, available_width) + self.compute_block_margins(*box, remaining_width, available_width) }; box.margin.set(SideOffsets2D::new(margin_top, @@ -727,11 +727,11 @@ impl Flow for BlockFlow { return; } - for &box in self.box.iter() { + for box in self.box.iter() { // The top margin collapses with its first in-flow block-level child's // top margin if the parent has no top border, no top padding. if *first_in_flow && top_margin_collapsible { - // If top-margin of parent is less than top-margin of its first child, + // If top-margin of parent is less than top-margin of its first child, // the parent box goes down until its top is aligned with the child. if *margin_top < box.margin.get().top { // TODO: The position of child floats should be updated and this @@ -741,7 +741,7 @@ impl Flow for BlockFlow { *margin_top = box.margin.get().top; } } - // The bottom margin of an in-flow block-level element collapses + // The bottom margin of an in-flow block-level element collapses // with the top margin of its next in-flow block-level sibling. *collapsing = geometry::min(box.margin.get().top, *collapsible); *collapsible = box.margin.get().bottom; @@ -760,7 +760,7 @@ impl Flow for BlockFlow { } else { let txt = if self.is_float() { ~"FloatFlow: " } else { ~"BlockFlow: " }; txt.append(match self.box { - Some(rb) => { + Some(ref rb) => { rb.debug_str() } None => { ~"" } diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs index 6328328459e..466aca72f71 100644 --- a/src/components/main/layout/box.rs +++ b/src/components/main/layout/box.rs @@ -5,7 +5,7 @@ //! The `Box` type, which represents the leaves of the layout tree. use extra::url::Url; -use extra::arc::MutexArc; +use extra::arc::{MutexArc, Arc}; use geom::{Point2D, Rect, Size2D, SideOffsets2D}; use gfx::color::rgb; use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass}; @@ -55,6 +55,7 @@ use layout::model::{MaybeAuto, specified}; /// types of boxes may also contain custom data; for example, text boxes contain text. /// /// FIXME(pcwalton): This can be slimmed down quite a bit. +#[deriving(Clone)] pub struct Box { /// The DOM node that this `Box` originates from. node: AbstractNode<LayoutView>, @@ -81,6 +82,7 @@ pub struct Box { } /// Info specific to the kind of box. Keep this enum small. +#[deriving(Clone)] pub enum SpecificBoxInfo { GenericBox, ImageBox(ImageBoxInfo), @@ -89,6 +91,7 @@ pub enum SpecificBoxInfo { } /// A box that represents a replaced content image and its accompanying borders, shadows, etc. +#[deriving(Clone)] pub struct ImageBoxInfo { /// The image held within this box. image: Slot<ImageHolder>, @@ -158,9 +161,10 @@ impl ImageBoxInfo { /// 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` /// object. +#[deriving(Clone)] pub struct ScannedTextBoxInfo { /// The text run that this represents. - run: @TextRun, + run: Arc<~TextRun>, /// The range within the above text run that this represents. range: Range, @@ -168,7 +172,7 @@ pub struct ScannedTextBoxInfo { impl ScannedTextBoxInfo { /// Creates the information specific to a scanned text box from a range and a text run. - pub fn new(run: @TextRun, range: Range) -> ScannedTextBoxInfo { + pub fn new(run: Arc<~TextRun>, range: Range) -> ScannedTextBoxInfo { ScannedTextBoxInfo { run: run, range: range, @@ -178,6 +182,7 @@ impl ScannedTextBoxInfo { /// Data for an unscanned text box. Unscanned text boxes are the results of flow construction that /// have not yet had their width determined. +#[deriving(Clone)] pub struct UnscannedTextBoxInfo { /// The text inside the box. text: ~str, @@ -197,11 +202,11 @@ impl UnscannedTextBoxInfo { /// Represents the outcome of attempting to split a box. pub enum SplitBoxResult { - CannotSplit(@Box), + CannotSplit, // in general, when splitting the left or right side can // be zero length, due to leading/trailing trimmable whitespace - SplitDidFit(Option<@Box>, Option<@Box>), - SplitDidNotFit(Option<@Box>, Option<@Box>) + SplitDidFit(Option<~Box>, Option<~Box>), + SplitDidNotFit(Option<~Box>, Option<~Box>) } impl Box { @@ -264,7 +269,7 @@ impl Box { self.position.set(Rect(self.position.get().origin, new_size)) } - pub fn calculate_line_height(&self, font_size: Au) -> Au { + pub fn calculate_line_height(&self, font_size: Au) -> Au { match self.line_height() { line_height::Normal => font_size.scale_by(1.14), line_height::Number(l) => font_size.scale_by(l), @@ -499,7 +504,7 @@ impl Box { /// Adds the display items necessary to paint the background of this box to the display list if /// necessary. pub fn paint_background_if_applicable<E:ExtraDisplayListData>( - @self, + &self, list: &Cell<DisplayList<E>>, absolute_bounds: &Rect<Au>) { // FIXME: This causes a lot of background colors to be displayed when they are clearly not @@ -515,7 +520,7 @@ impl Box { let solid_color_display_item = ~SolidColorDisplayItem { base: BaseDisplayItem { bounds: *absolute_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, color: background_color.to_gfx_color(), }; @@ -528,7 +533,7 @@ impl Box { /// Adds the display items necessary to paint the borders of this box to a display list if /// necessary. pub fn paint_borders_if_applicable<E:ExtraDisplayListData>( - @self, + &self, list: &Cell<DisplayList<E>>, abs_bounds: &Rect<Au>) { // Fast path. @@ -552,7 +557,7 @@ impl Box { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: *abs_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, border: border, color: SideOffsets2D::new(top_color.to_gfx_color(), @@ -584,7 +589,7 @@ impl Box { /// items, each box puts its display items into the correct stack layer according to CSS 2.1 /// Appendix E. Finally, the builder flattens the list. pub fn build_display_list<E:ExtraDisplayListData>( - @self, + &self, _: &DisplayListBuilder, dirty: &Rect<Au>, offset: &Point2D<Au>, @@ -616,7 +621,7 @@ impl Box { let item = ~ClipDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, child_list: ~[], need_clip: false @@ -631,18 +636,11 @@ impl Box { // Create the text box. do list.with_mut_ref |list| { // FIXME(pcwalton): Allocation? Why?! - let run = ~TextRun { - text: text_box.run.text.clone(), - font_descriptor: text_box.run.font_descriptor.clone(), - font_metrics: text_box.run.font_metrics.clone(), - font_style: text_box.run.font_style.clone(), - decoration: text_box.run.decoration.clone(), - glyphs: text_box.run.glyphs.clone() - }; + let run = text_box.run.clone(); let text_display_item = ~TextDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, text_run: run, range: text_box.range, @@ -664,7 +662,7 @@ impl Box { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, border: debug_border, color: SideOffsets2D::new_all_same(rgb(0, 0, 200)), @@ -677,7 +675,7 @@ impl Box { // Draw a rectangle representing the baselines. // // TODO(Issue #221): Create and use a Line display item for the baseline. - let ascent = text_box.run.metrics_for_range( + let ascent = text_box.run.get().metrics_for_range( &text_box.range).ascent; let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent), Size2D(absolute_box_bounds.size.width, Au(0))); @@ -686,7 +684,7 @@ impl Box { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: baseline, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, border: debug_border, color: SideOffsets2D::new_all_same(rgb(0, 200, 0)), @@ -704,7 +702,7 @@ impl Box { let item = ~ClipDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, child_list: ~[], need_clip: self.needs_clip() @@ -721,7 +719,7 @@ impl Box { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, border: debug_border, color: SideOffsets2D::new_all_same(rgb(0, 0, 200)), @@ -739,7 +737,7 @@ impl Box { let item = ~ClipDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, child_list: ~[], need_clip: false @@ -756,7 +754,7 @@ impl Box { let image_display_item = ~ImageDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, - extra: ExtraDisplayListData::new(&self), + extra: ExtraDisplayListData::new(self), }, image: image.clone(), }; @@ -790,11 +788,11 @@ impl Box { } ScannedTextBox(ref text_box_info) => { let range = &text_box_info.range; - let min_line_width = text_box_info.run.min_width_for_range(range); + let min_line_width = text_box_info.run.get().min_width_for_range(range); let mut max_line_width = Au::new(0); - for line_range in text_box_info.run.iter_natural_lines_for_range(range) { - let line_metrics = text_box_info.run.metrics_for_range(&line_range); + for line_range in text_box_info.run.get().iter_natural_lines_for_range(range) { + let line_metrics = text_box_info.run.get().metrics_for_range(&line_range); max_line_width = Au::max(max_line_width, line_metrics.advance_width); } @@ -825,7 +823,7 @@ impl Box { ScannedTextBox(ref text_box_info) => { // Compute the height based on the line-height and font size. let (range, run) = (&text_box_info.range, &text_box_info.run); - let text_bounds = run.metrics_for_range(range).bounding_box; + let text_bounds = run.get().metrics_for_range(range).bounding_box; let em_size = text_bounds.size.height; self.calculate_line_height(em_size) } @@ -834,9 +832,9 @@ 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 { + pub fn split_to_width(&self, max_width: Au, starts_line: bool) -> SplitBoxResult { match self.specific { - GenericBox | ImageBox(_) => CannotSplit(self), + GenericBox | 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; @@ -846,11 +844,11 @@ impl Box { debug!("split_to_width: splitting text box (strlen={:u}, range={}, \ avail_width={})", - text_box_info.run.text.get().len(), + text_box_info.run.get().text.get().len(), text_box_info.range, max_width); - for (glyphs, offset, slice_range) in text_box_info.run.iter_slices_for_range( + for (glyphs, offset, slice_range) in text_box_info.run.get().iter_slices_for_range( &text_box_info.range) { debug!("split_to_width: considering slice (offset={}, range={}, \ remain_width={})", @@ -858,7 +856,7 @@ impl Box { slice_range, remaining_width); - let metrics = text_box_info.run.metrics_for_slice(glyphs, &slice_range); + let metrics = text_box_info.run.get().metrics_for_slice(glyphs, &slice_range); let advance = metrics.advance_width; let should_continue; @@ -909,9 +907,9 @@ impl Box { } let left_box = if left_range.length() > 0 { - let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run, left_range); - let new_text_box = @Box::new(self.node, ScannedTextBox(new_text_box_info)); - let new_metrics = new_text_box_info.run.metrics_for_range(&left_range); + let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), left_range); + let new_metrics = new_text_box_info.run.get().metrics_for_range(&left_range); + let new_text_box = ~Box::new(self.node, ScannedTextBox(new_text_box_info)); new_text_box.set_size(new_metrics.bounding_box.size); Some(new_text_box) } else { @@ -919,9 +917,9 @@ impl Box { }; let right_box = right_range.map_default(None, |range: Range| { - let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run, range); - let new_text_box = @Box::new(self.node, ScannedTextBox(new_text_box_info)); - let new_metrics = new_text_box_info.run.metrics_for_range(&range); + let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), range); + let new_metrics = new_text_box_info.run.get().metrics_for_range(&range); + let new_text_box = ~Box::new(self.node, ScannedTextBox(new_text_box_info)); new_text_box.set_size(new_metrics.bounding_box.size); Some(new_text_box) }); @@ -975,7 +973,7 @@ impl Box { /// Cleans up all the memory associated with this box. pub fn teardown(&self) { match self.specific { - ScannedTextBox(ref text_box_info) => text_box_info.run.teardown(), + ScannedTextBox(ref text_box_info) => text_box_info.run.get().teardown(), _ => {} } } diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs index 18ff1654888..8eaa6d25c80 100644 --- a/src/components/main/layout/construct.rs +++ b/src/components/main/layout/construct.rs @@ -7,7 +7,7 @@ //! Each step of the traversal considers the node and existing flow, if there is one. If a node is //! not dirty and an existing flow exists, then the traversal reuses that flow. Otherwise, it //! proceeds to construct either a flow or a `ConstructionItem`. A construction item is a piece of -//! intermediate data that goes with a DOM node and hasn't found its "home" yet—maybe it's a box, +//! intermediate data that goes with a DOM node and hasn't found its "home" yet-maybe it's a box, //! maybe it's an absolute or fixed position thing that hasn't found its containing block yet. //! Construction items bubble up the tree from children to parents until they find their homes. //! @@ -70,7 +70,7 @@ struct InlineBoxesConstructionResult { splits: Option<~[InlineBlockSplit]>, /// Any boxes that succeed the {ib} splits. - boxes: ~[@Box], + boxes: ~[~Box], } /// Represents an {ib} split that has not yet found the containing block that it belongs to. This @@ -99,7 +99,7 @@ struct InlineBlockSplit { /// The inline boxes that precede the flow. /// /// TODO(pcwalton): Small vector optimization. - predecessor_boxes: ~[@Box], + predecessor_boxes: ~[~Box], /// The flow that caused this {ib} split. flow: ~Flow:, @@ -215,7 +215,7 @@ impl<'self> FlowConstructor<'self> { } /// Builds a `Box` for the given node. - fn build_box_for_node(&self, node: AbstractNode<LayoutView>) -> @Box { + fn build_box_for_node(&self, node: AbstractNode<LayoutView>) -> ~Box { let specific = match node.type_id() { ElementNodeTypeId(HTMLImageElementTypeId) => { match self.build_box_info_for_image(node) { @@ -226,7 +226,7 @@ impl<'self> FlowConstructor<'self> { TextNodeTypeId => UnscannedTextBox(UnscannedTextBoxInfo::new(&node)), _ => GenericBox, }; - @Box::new(node, specific) + ~Box::new(node, specific) } /// Creates an inline flow from a set of inline boxes and adds it as a child of the given flow. @@ -235,7 +235,7 @@ impl<'self> FlowConstructor<'self> { /// otherwise. #[inline(always)] fn flush_inline_boxes_to_flow(&self, - boxes: ~[@Box], + boxes: ~[~Box], flow: &mut ~Flow:, node: AbstractNode<LayoutView>) { if boxes.len() > 0 { @@ -249,7 +249,7 @@ impl<'self> FlowConstructor<'self> { /// Creates an inline flow from a set of inline boxes, if present, and adds it as a child of /// the given flow. fn flush_inline_boxes_to_flow_if_necessary(&self, - opt_boxes: &mut Option<~[@Box]>, + opt_boxes: &mut Option<~[~Box]>, flow: &mut ~Flow:, node: AbstractNode<LayoutView>) { let opt_boxes = util::replace(opt_boxes, None); @@ -564,7 +564,7 @@ impl NodeUtils for AbstractNode<LayoutView> { } /// Strips ignorable whitespace from the start of a list of boxes. -fn strip_ignorable_whitespace_from_start(opt_boxes: &mut Option<~[@Box]>) { +fn strip_ignorable_whitespace_from_start(opt_boxes: &mut Option<~[~Box]>) { match util::replace(opt_boxes, None) { None => return, Some(boxes) => { @@ -586,7 +586,7 @@ fn strip_ignorable_whitespace_from_start(opt_boxes: &mut Option<~[@Box]>) { } /// Strips ignorable whitespace from the end of a list of boxes. -fn strip_ignorable_whitespace_from_end(opt_boxes: &mut Option<~[@Box]>) { +fn strip_ignorable_whitespace_from_end(opt_boxes: &mut Option<~[~Box]>) { match *opt_boxes { None => {} Some(ref mut boxes) => { diff --git a/src/components/main/layout/display_list_builder.rs b/src/components/main/layout/display_list_builder.rs index b75c508a733..ae583e72334 100644 --- a/src/components/main/layout/display_list_builder.rs +++ b/src/components/main/layout/display_list_builder.rs @@ -16,13 +16,13 @@ use style; /// that nodes in this view shoud not really be touched. The idea is to /// store the nodes in the display list and have layout transmute them. pub trait ExtraDisplayListData { - fn new(box: &@Box) -> Self; + fn new(box: &Box) -> Self; } pub type Nothing = (); impl ExtraDisplayListData for AbstractNode<()> { - fn new(box: &@Box) -> AbstractNode<()> { + fn new(box: &Box) -> AbstractNode<()> { unsafe { transmute(box.node) } @@ -30,7 +30,7 @@ impl ExtraDisplayListData for AbstractNode<()> { } impl ExtraDisplayListData for Nothing { - fn new(_: &@Box) -> Nothing { + fn new(_: &Box) -> Nothing { () } } diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 151a702fe84..faa0c2c79db 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -29,22 +29,22 @@ use std::util; /// as an object that "owns" boxes. Choosing a different set of line /// breaks requires a new list of offsets, and possibly some splitting and /// merging of TextBoxes. -/// +/// /// A similar list will keep track of the mapping between CSS boxes and /// the corresponding boxes in the inline flow. -/// +/// /// After line breaks are determined, render boxes in the inline flow may /// overlap visually. For example, in the case of nested inline CSS boxes, /// outer inlines must be at least as large as the inner inlines, for /// purposes of drawing noninherited things like backgrounds, borders, /// outlines. -/// +/// /// N.B. roc has an alternative design where the list instead consists of /// things like "start outer box, text, start inner box, text, end inner /// box, text, end outer box, text". This seems a little complicated to /// serve as the starting point, but the current design doesn't make it /// hard to try out that alternative. -/// +/// /// Line boxes also contain some metadata used during line breaking. The /// green zone is the area that the line can expand to before it collides /// with a float or a horizontal wall of the containing block. The top @@ -58,15 +58,13 @@ struct LineBox { struct LineboxScanner { floats: FloatContext, - new_boxes: ~[@Box], - work_list: RingBuf<@Box>, + new_boxes: ~[~Box], + work_list: RingBuf<~Box>, pending_line: LineBox, lines: ~[LineBox], cur_y: Au, } -local_data_key!(local_linebox_scanner: LineboxScanner) - impl LineboxScanner { pub fn new(float_ctx: FloatContext) -> LineboxScanner { LineboxScanner { @@ -74,8 +72,8 @@ impl LineboxScanner { new_boxes: ~[], work_list: RingBuf::new(), pending_line: LineBox { - range: Range::empty(), - bounds: Rect(Point2D(Au::new(0), Au::new(0)), Size2D(Au::new(0), Au::new(0))), + range: Range::empty(), + bounds: Rect(Point2D(Au::new(0), Au::new(0)), Size2D(Au::new(0), Au::new(0))), green_zone: Size2D(Au::new(0), Au::new(0)) }, lines: ~[], @@ -94,7 +92,7 @@ impl LineboxScanner { self.lines.truncate(0); self.cur_y = Au::new(0); } - + pub fn floats_out(&mut self) -> FloatContext { self.floats.clone() } @@ -116,15 +114,13 @@ impl LineboxScanner { pub fn scan_for_lines(&mut self, flow: &mut InlineFlow) { self.reset_scanner(flow); - let mut i = 0u; - loop { // acquire the next box to lay out from work list or box list let cur_box = if self.work_list.is_empty() { - if i == flow.boxes.len() { - break + if flow.boxes.is_empty() { + break; } - let box = flow.boxes[i]; i += 1; + let box = flow.boxes.remove(0); // FIXME: use a linkedlist debug!("LineboxScanner: Working with box from box list: b{}", box.debug_id()); box } else { @@ -188,7 +184,7 @@ impl LineboxScanner { /// Computes the position of a line that has only the provided box. Returns the bounding rect /// of the line's green zone (whose origin coincides with the line's origin) and the actual /// width of the first box after splitting. - fn initial_line_placement(&self, first_box: @Box, ceiling: Au, flow: &mut InlineFlow) + fn initial_line_placement(&self, first_box: &Box, ceiling: Au, flow: &mut InlineFlow) -> (Rect<Au>, Au) { debug!("LineboxScanner: Trying to place first box of line {}", self.lines.len()); @@ -219,7 +215,7 @@ impl LineboxScanner { debug!("LineboxScanner: found position for line: {} using placement_info: {:?}", line_bounds, info); - + // Simple case: if the box fits, then we can stop here if line_bounds.size.width > first_box_size.width { debug!("LineboxScanner: case=box fits"); @@ -238,7 +234,7 @@ impl LineboxScanner { // We should find a better abstraction or merge it with the call in // try_append_to_line. match first_box.split_to_width(line_bounds.size.width, line_is_empty) { - CannotSplit(_) => { + CannotSplit => { error!("LineboxScanner: Tried to split unsplittable render box! {:s}", first_box.debug_str()); return (line_bounds, first_box_size.width); @@ -274,7 +270,7 @@ impl LineboxScanner { return (new_bounds, actual_box_width); } } - + } /// Performs float collision avoidance. This is called when adding a box is going to increase @@ -292,7 +288,7 @@ impl LineboxScanner { /// /// Returns false if and only if we should break the line. fn avoid_floats(&mut self, - in_box: @Box, + in_box: ~Box, flow: &mut InlineFlow, new_height: Au, line_is_empty: bool) @@ -325,7 +321,7 @@ impl LineboxScanner { /// Tries to append the given box to the line, splitting it if necessary. Returns false only if /// we should break the line. - fn try_append_to_line(&mut self, in_box: @Box, flow: &mut InlineFlow) -> bool { + fn try_append_to_line(&mut self, in_box: ~Box, flow: &mut InlineFlow) -> bool { let line_is_empty = self.pending_line.range.length() == 0; if line_is_empty { let (line_bounds, _) = self.initial_line_placement(in_box, self.cur_y, flow); @@ -348,7 +344,7 @@ impl LineboxScanner { let new_height = self.new_height_for_line(in_box); if new_height > green_zone.height { - // Uh-oh. Float collision imminent. Enter the float collision avoider… + // Uh-oh. Float collision imminent. Enter the float collision avoider return self.avoid_floats(in_box, flow, new_height, line_is_empty) } @@ -379,7 +375,7 @@ impl LineboxScanner { let available_width = green_zone.width - self.pending_line.bounds.size.width; let split = in_box.split_to_width(available_width, line_is_empty); let (left, right) = match (split, line_is_empty) { - (CannotSplit(_), _) => { + (CannotSplit, _) => { error!("LineboxScanner: Tried to split unsplittable render box! {:s}", in_box.debug_str()); return false @@ -418,8 +414,8 @@ impl LineboxScanner { true } - // An unconditional push. - fn push_box_to_line(&mut self, box: @Box) { + // An unconditional push + fn push_box_to_line(&mut self, box: ~Box) { debug!("LineboxScanner: Pushing box {} to line {:u}", box.debug_id(), self.lines.len()); if self.pending_line.range.length() == 0 { @@ -429,7 +425,7 @@ impl LineboxScanner { self.pending_line.range.extend_by(1); self.pending_line.bounds.size.width = self.pending_line.bounds.size.width + box.position.get().size.width; - self.pending_line.bounds.size.height = Au::max(self.pending_line.bounds.size.height, + self.pending_line.bounds.size.height = Au::max(self.pending_line.bounds.size.height, box.position.get().size.height); self.new_boxes.push(box); } @@ -440,7 +436,7 @@ pub struct InlineFlow { base: FlowData, /// A vector of all inline render boxes. Several boxes may correspond to one node/element. - boxes: ~[@Box], + boxes: ~[~Box], // vec of ranges into boxes that represents line positions. // these ranges are disjoint, and are the result of inline layout. @@ -462,7 +458,7 @@ impl InlineFlow { } } - pub fn from_boxes(base: FlowData, boxes: ~[@Box]) -> InlineFlow { + pub fn from_boxes(base: FlowData, boxes: ~[~Box]) -> InlineFlow { InlineFlow { base: base, boxes: boxes, @@ -506,7 +502,7 @@ impl InlineFlow { // TODO(#225): Should `inline-block` elements have flows as children of the inline flow or // should the flow be nested inside the box somehow? - + // For now, don't traverse the subtree rooted here true } @@ -516,7 +512,7 @@ impl InlineFlow { /// /// The extra boolean is set if and only if `biggest_top` and/or `biggest_bottom` were updated. /// That is, if the box has a `top` or `bottom` value, true is returned. - fn relative_offset_from_baseline(cur_box: @Box, + fn relative_offset_from_baseline(cur_box: &Box, ascent: Au, parent_text_top: Au, parent_text_bottom: Au, @@ -574,7 +570,7 @@ impl InlineFlow { }, vertical_align::Length(length) => (-(length + ascent), false), vertical_align::Percentage(p) => { - let pt_size = cur_box.font_style().pt_size; + let pt_size = cur_box.font_style().pt_size; let line_height = cur_box.calculate_line_height(Au::from_pt(pt_size)); let percent_offset = line_height.scale_by(p); (-(percent_offset + ascent), false) @@ -583,7 +579,7 @@ impl InlineFlow { } /// Sets box X positions based on alignment for one line. - fn set_horizontal_box_positions(boxes: &[@Box], line: &LineBox) { + fn set_horizontal_box_positions(boxes: &[~Box], line: &LineBox) { // Figure out how much width we have. let slack_width = Au::max(Au(0), line.green_zone.width - line.bounds.size.width); @@ -592,7 +588,7 @@ impl InlineFlow { // TODO(burg, issue #222): use 'text-align' property from `InlineFlow`'s block container, // not from the style of the first box child. let linebox_align = if line.range.begin() < boxes.len() { - let first_box = boxes[line.range.begin()]; + let first_box = &boxes[line.range.begin()]; first_box.nearest_ancestor_element().style().Text.text_align } else { // Nothing to lay out, so assume left alignment. @@ -668,7 +664,7 @@ impl Flow for InlineFlow { debug!("assign_widths_inline: floats_in: {:?}", self.base.floats_in); { let this = &mut *self; - for &box in this.boxes.iter() { + for box in this.boxes.iter() { box.assign_width(); } } @@ -732,12 +728,12 @@ impl Flow for InlineFlow { let (mut biggest_top, mut biggest_bottom) = (Au(0), Au(0)); for box_i in line.range.eachi() { - let cur_box = self.boxes[box_i]; + let cur_box = &self.boxes[box_i]; // FIXME(pcwalton): Move into `box.rs` like the rest of box-specific layout code? let (top_from_base, bottom_from_base, ascent) = match cur_box.specific { ImageBox(ref image_box) => { - let mut height = image_box.image_height(cur_box); + let mut height = image_box.image_height(*cur_box); // TODO: margin, border, padding's top and bottom should be calculated in // advance, since baseline of image is bottom margin edge. @@ -763,16 +759,16 @@ impl Flow for InlineFlow { ScannedTextBox(ref text_box) => { let range = &text_box.range; let run = &text_box.run; - + // Compute the height based on the line-height and font size - let text_bounds = run.metrics_for_range(range).bounding_box; + let text_bounds = run.get().metrics_for_range(range).bounding_box; let em_size = text_bounds.size.height; let line_height = cur_box.calculate_line_height(em_size); // Find the top and bottom of the content area. // Those are used in text-top and text-bottom value of 'vertical-align' - let text_ascent = text_box.run.font_metrics.ascent; - + let text_ascent = text_box.run.get().font_metrics.ascent; + // Offset from the top of the box is 1/2 of the leading + ascent let text_offset = text_ascent + (line_height - em_size).scale_by(0.5); text_bounds.translate(&Point2D(cur_box.position.get().origin.x, Au(0))); @@ -794,7 +790,7 @@ impl Flow for InlineFlow { // To calculate text-top and text-bottom value of 'vertical-align', // we should find the top and bottom of the content area of parent box. // The content area is defined in: - // http://www.w3.org/TR/CSS2/visudet.html#inline-non-replaced + // http://www.w3.org/TR/CSS2/visudet.html#inline-non-replaced // // TODO: We should extract em-box info from the font size of the parent and // calculate the distances from the baseline to the top and the bottom of the @@ -818,7 +814,7 @@ impl Flow for InlineFlow { // updated or not. That is, if the box has a `top` or `bottom` value, // `no_update_flag` becomes true. let (offset, no_update_flag) = - InlineFlow::relative_offset_from_baseline(cur_box, + InlineFlow::relative_offset_from_baseline(*cur_box, ascent, parent_text_top, parent_text_bottom, @@ -858,7 +854,7 @@ impl Flow for InlineFlow { // All boxes' y position is updated following the new baseline offset. for box_i in line.range.eachi() { - let cur_box = self.boxes[box_i]; + let cur_box = &self.boxes[box_i]; let adjust_offset = match cur_box.vertical_align() { vertical_align::top => Au::new(0), vertical_align::bottom => baseline_offset + bottommost, @@ -875,7 +871,7 @@ impl Flow for InlineFlow { line.bounds.size.height = topmost + bottommost; } // End of `lines.each` loop. - self.base.position.size.height = + self.base.position.size.height = if self.lines.len() > 0 { self.lines.last().bounds.origin.y + self.lines.last().bounds.size.height } else { diff --git a/src/components/main/layout/text.rs b/src/components/main/layout/text.rs index e42ede37b56..9f66f006859 100644 --- a/src/components/main/layout/text.rs +++ b/src/components/main/layout/text.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! Text layout. - +use extra::arc::Arc; use layout::box::{Box, ScannedTextBox, ScannedTextBoxInfo, UnscannedTextBox}; use layout::context::LayoutContext; use layout::flow::Flow; @@ -56,7 +56,7 @@ impl TextRunScanner { flow.as_inline().boxes = out_boxes; // A helper function. - fn can_coalesce_text_nodes(boxes: &[@Box], left_i: uint, right_i: uint) -> bool { + fn can_coalesce_text_nodes(boxes: &[~Box], left_i: uint, right_i: uint) -> bool { assert!(left_i < boxes.len()); assert!(right_i > 0 && right_i < boxes.len()); assert!(left_i != right_i); @@ -78,17 +78,17 @@ impl TextRunScanner { ctx: &LayoutContext, flow: &mut Flow, last_whitespace: bool, - out_boxes: &mut ~[@Box]) + out_boxes: &mut ~[~Box]) -> bool { let inline = flow.as_inline(); - let in_boxes = &inline.boxes; + let in_boxes = &mut inline.boxes; assert!(self.clump.length() > 0); debug!("TextRunScanner: flushing boxes in range={}", self.clump); let is_singleton = self.clump.length() == 1; - let possible_text_clump = in_boxes[self.clump.begin()]; // FIXME(pcwalton): Rust bug - let is_text_clump = match possible_text_clump.specific { + + let is_text_clump = match in_boxes[self.clump.begin()].specific { UnscannedTextBox(_) => true, _ => false, }; @@ -100,10 +100,12 @@ impl TextRunScanner { } (true, false) => { debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump); - out_boxes.push(in_boxes[self.clump.begin()]); + // out_boxes.push(in_boxes[self.clump.begin()]); + let first_box = in_boxes.remove(self.clump.begin()); + out_boxes.push(first_box); }, (true, true) => { - let old_box = in_boxes[self.clump.begin()]; + let old_box = &in_boxes[self.clump.begin()]; let text = match old_box.specific { UnscannedTextBox(ref text_box_info) => &text_box_info.text, _ => fail!("Expected an unscanned text box!"), @@ -125,15 +127,15 @@ impl TextRunScanner { // font group fonts. This is probably achieved by creating the font group above // and then letting `FontGroup` decide which `Font` to stick into the text run. let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); - let run = @fontgroup.with_borrow(|fg| fg.create_textrun(transformed_text.clone(), decoration)); + let run = ~fontgroup.with_borrow(|fg| fg.create_textrun(transformed_text.clone(), decoration)); debug!("TextRunScanner: pushing single text box in range: {} ({})", self.clump, *text); let range = Range::new(0, run.char_len()); - let new_text_box_info = ScannedTextBoxInfo::new(run, range); let new_metrics = run.metrics_for_range(&range); - let new_box = @old_box.transform(new_metrics.bounding_box.size, + let new_text_box_info = ScannedTextBoxInfo::new(Arc::new(run), range); + let new_box = ~old_box.transform(new_metrics.bounding_box.size, ScannedTextBox(new_text_box_info)); out_boxes.push(new_box) } @@ -179,7 +181,7 @@ impl TextRunScanner { // TODO(#177): Text run creation must account for the renderability of text by // font group fonts. This is probably achieved by creating the font group above // and then letting `FontGroup` decide which `Font` to stick into the text run. - let in_box = in_boxes[self.clump.begin()]; + let in_box = &in_boxes[self.clump.begin()]; let font_style = in_box.font_style(); let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); let decoration = in_box.text_decoration(); @@ -190,7 +192,7 @@ impl TextRunScanner { let run = if clump.length() != 0 && run_str.len() > 0 { fontgroup.with_borrow( |fg| { fg.fonts[0].with_mut_borrow( |font| { - Some(@TextRun::new(font, run_str.clone(), decoration)) + Some(Arc::new(~TextRun::new(font, run_str.clone(), decoration))) }) }) } else { @@ -208,9 +210,9 @@ impl TextRunScanner { continue } - let new_text_box_info = ScannedTextBoxInfo::new(run.unwrap(), range); - let new_metrics = new_text_box_info.run.metrics_for_range(&range); - let new_box = @in_boxes[i].transform(new_metrics.bounding_box.size, + let new_text_box_info = ScannedTextBoxInfo::new(run.get_ref().clone(), range); + let new_metrics = new_text_box_info.run.get().metrics_for_range(&range); + let new_box = ~in_boxes[i].transform(new_metrics.bounding_box.size, ScannedTextBox(new_text_box_info)); out_boxes.push(new_box) } diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs index 9a879295f5e..1aa222cf207 100644 --- a/src/components/main/layout/util.rs +++ b/src/components/main/layout/util.rs @@ -56,7 +56,7 @@ impl ElementMapping { self.entries.iter().enumerate() } - pub fn repair_for_box_changes(&mut self, old_boxes: &[@Box], new_boxes: &[@Box]) { + pub fn repair_for_box_changes(&mut self, old_boxes: &[~Box], new_boxes: &[~Box]) { let entries = &mut self.entries; debug!("--- Old boxes: ---"); diff --git a/src/components/net/image/holder.rs b/src/components/net/image/holder.rs index cdaa697fcaf..5b312fffe4f 100644 --- a/src/components/net/image/holder.rs +++ b/src/components/net/image/holder.rs @@ -17,6 +17,7 @@ use extra::arc::{Arc, MutexArc}; /// A struct to store image data. The image will be loaded once the first time it is requested, /// and an Arc will be stored. Clones of this Arc are given out on demand. +#[deriving(Clone)] pub struct ImageHolder { url: Url, image: Option<Arc<~Image>>, @@ -59,7 +60,7 @@ impl ImageHolder { pub fn size(&self) -> Size2D<int> { self.cached_size } - + /// Query and update the current image size. pub fn get_size(&mut self) -> Option<Size2D<int>> { debug!("get_size() {}", self.url.to_str()); |