mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
removing @ from flowtree. (but cloning boxes when creating a display list)
This commit is contained in:
parent
6014bd3813
commit
d26bf36833
9 changed files with 156 additions and 158 deletions
|
@ -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));
|
||||
|
|
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -464,16 +464,16 @@ impl BlockFlow {
|
|||
}
|
||||
|
||||
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| {
|
||||
|
@ -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,7 +727,7 @@ 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 {
|
||||
|
@ -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 => { ~"" }
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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 {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -765,13 +761,13 @@ impl Flow for InlineFlow {
|
|||
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);
|
||||
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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: ---");
|
||||
|
|
|
@ -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>>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue