mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
implement inline border
This commit is contained in:
parent
882cc0bf69
commit
c2ced790ba
7 changed files with 390 additions and 58 deletions
|
@ -649,6 +649,7 @@ impl Flow for BlockFlow {
|
||||||
// The text alignment of a block flow is the text alignment of its box's style.
|
// The text alignment of a block flow is the text alignment of its box's style.
|
||||||
self.base.flags_info.flags.set_text_align(style.Text.text_align);
|
self.base.flags_info.flags.set_text_align(style.Text.text_align);
|
||||||
|
|
||||||
|
box_.assign_width(remaining_width);
|
||||||
// Can compute padding here since we know containing block width.
|
// Can compute padding here since we know containing block width.
|
||||||
box_.compute_padding(style, remaining_width);
|
box_.compute_padding(style, remaining_width);
|
||||||
|
|
||||||
|
@ -739,6 +740,11 @@ impl Flow for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_height(&mut self, ctx: &mut LayoutContext) {
|
fn assign_height(&mut self, ctx: &mut LayoutContext) {
|
||||||
|
//assign height for box
|
||||||
|
for box_ in self.box_.iter() {
|
||||||
|
box_.assign_height();
|
||||||
|
}
|
||||||
|
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
debug!("assign_height_float: assigning height for float {}", self.base.id);
|
debug!("assign_height_float: assigning height for float {}", self.base.id);
|
||||||
self.assign_height_float(ctx);
|
self.assign_height_float(ctx);
|
||||||
|
|
|
@ -151,7 +151,7 @@ impl ImageBoxInfo {
|
||||||
width
|
width
|
||||||
},
|
},
|
||||||
&None => {
|
&None => {
|
||||||
fail!("width is not computed yet!");
|
fail!("image width is not computed yet!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ impl ImageBoxInfo {
|
||||||
height
|
height
|
||||||
},
|
},
|
||||||
&None => {
|
&None => {
|
||||||
fail!("image size is not computed yet!");
|
fail!("image height is not computed yet!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,6 +291,7 @@ pub struct InlineParentInfo {
|
||||||
style: Arc<ComputedValues>,
|
style: Arc<ComputedValues>,
|
||||||
font_ascent: Au,
|
font_ascent: Au,
|
||||||
font_descent: Au,
|
font_descent: Au,
|
||||||
|
node: OpaqueNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -511,18 +512,164 @@ impl Box {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noncontent_width(&self) -> Au {
|
pub fn noncontent_width(&self) -> Au {
|
||||||
let left = self.margin.get().left + self.border.get().left + self.padding.get().left;
|
self.noncontent_left() + self.noncontent_right()
|
||||||
let right = self.margin.get().right + self.border.get().right + self.padding.get().right;
|
|
||||||
left + right
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noncontent_height(&self) -> Au {
|
pub fn noncontent_height(&self) -> Au {
|
||||||
let top = self.margin.get().top + self.border.get().top + self.padding.get().top;
|
self.noncontent_top() + self.noncontent_bottom()
|
||||||
let bottom = self.margin.get().bottom + self.border.get().bottom +
|
|
||||||
self.padding.get().bottom;
|
|
||||||
top + bottom
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_left(&self) -> Au {
|
||||||
|
self.margin.get().left + self.border.get().left + self.padding.get().left
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_right(&self) -> Au {
|
||||||
|
self.margin.get().right + self.border.get().right + self.padding.get().right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_top(&self) -> Au {
|
||||||
|
self.margin.get().top + self.border.get().top + self.padding.get().top
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_bottom(&self) -> Au {
|
||||||
|
self.margin.get().bottom + self.border.get().bottom + self.padding.get().bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_inline_left(&self) -> Au {
|
||||||
|
let mut left = Au::new(0);
|
||||||
|
let info = self.inline_info.borrow();
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref info) => {
|
||||||
|
for info in info.parent_info.iter() {
|
||||||
|
left = left + info.margin.left + info.border.left + info.padding.left;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
left
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_inline_right(&self) -> Au {
|
||||||
|
let mut right = Au::new(0);
|
||||||
|
let info = self.inline_info.borrow();
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref info) => {
|
||||||
|
for info in info.parent_info.iter() {
|
||||||
|
right = right + info.margin.right + info.border.right + info.padding.right;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_inline_top(&self) -> Au {
|
||||||
|
let mut top = Au::new(0);
|
||||||
|
let info = self.inline_info.borrow();
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref info) => {
|
||||||
|
for info in info.parent_info.iter() {
|
||||||
|
top = top + info.margin.top + info.border.top + info.padding.top;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
top
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noncontent_inline_bottom(&self) -> Au {
|
||||||
|
let mut bottom = Au::new(0);
|
||||||
|
let info = self.inline_info.borrow();
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref info) => {
|
||||||
|
for info in info.parent_info.iter() {
|
||||||
|
bottom = bottom + info.margin.bottom + info.border.bottom + info.padding.bottom;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge_noncontent_inline_right(&self, other_box: &Box) {
|
||||||
|
let mut info = self.inline_info.borrow_mut();
|
||||||
|
let other_info = other_box.inline_info.borrow();
|
||||||
|
|
||||||
|
match other_info.get() {
|
||||||
|
&Some(ref other_info) => {
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref mut info) => {
|
||||||
|
for other_item in other_info.parent_info.iter() {
|
||||||
|
for item in info.parent_info.mut_iter() {
|
||||||
|
if item.node == other_item.node {
|
||||||
|
item.border.right = other_item.border.right;
|
||||||
|
item.padding.right = other_item.padding.right;
|
||||||
|
item.margin.right = other_item.margin.right;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge_noncontent_inline_left(&self, other_box: &Box) {
|
||||||
|
let mut info = self.inline_info.borrow_mut();
|
||||||
|
let other_info = other_box.inline_info.borrow();
|
||||||
|
|
||||||
|
match other_info.get() {
|
||||||
|
&Some(ref other_info) => {
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref mut info) => {
|
||||||
|
for other_item in other_info.parent_info.iter() {
|
||||||
|
for item in info.parent_info.mut_iter() {
|
||||||
|
if item.node == other_item.node {
|
||||||
|
item.border.left = other_item.border.left;
|
||||||
|
item.padding.left = other_item.padding.left;
|
||||||
|
item.margin.left = other_item.margin.left;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_noncontent_inline_right(&self) {
|
||||||
|
let mut info = self.inline_info.borrow_mut();
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref mut info) => {
|
||||||
|
for item in info.parent_info.mut_iter() {
|
||||||
|
item.border.right = Au::new(0);
|
||||||
|
item.padding.right = Au::new(0);
|
||||||
|
item.margin.right = Au::new(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_noncontent_inline_left(&self) {
|
||||||
|
let mut info = self.inline_info.borrow_mut();
|
||||||
|
match info.get() {
|
||||||
|
&Some(ref mut info) => {
|
||||||
|
for item in info.parent_info.mut_iter() {
|
||||||
|
item.border.left = Au::new(0);
|
||||||
|
item.padding.left = Au::new(0);
|
||||||
|
item.margin.left = Au::new(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Always inline for SCCP.
|
/// Always inline for SCCP.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): Just replace with the clear type from the style module for speed?
|
/// FIXME(pcwalton): Just replace with the clear type from the style module for speed?
|
||||||
|
@ -635,9 +782,7 @@ impl Box {
|
||||||
(Au::new(0), Au::new(0))
|
(Au::new(0), Au::new(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background of this box to the display list if
|
pub fn paint_inline_background_border_if_applicable<E:ExtraDisplayListData>(
|
||||||
/// necessary.
|
|
||||||
pub fn paint_background_if_applicable<E:ExtraDisplayListData>(
|
|
||||||
&self,
|
&self,
|
||||||
list: &RefCell<DisplayList<E>>,
|
list: &RefCell<DisplayList<E>>,
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
|
@ -670,11 +815,62 @@ impl Box {
|
||||||
list.append_item(SolidColorDisplayItemClass(solid_color_display_item))
|
list.append_item(SolidColorDisplayItemClass(solid_color_display_item))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let border = &info.border;
|
||||||
|
// Fast path.
|
||||||
|
if border.is_zero() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bg_rect.origin.y = bg_rect.origin.y - border.top;
|
||||||
|
bg_rect.size.height = bg_rect.size.height + border.top + border.bottom;
|
||||||
|
|
||||||
|
let style = info.style.get();
|
||||||
|
let top_color = style.resolve_color(style.Border.border_top_color);
|
||||||
|
let right_color = style.resolve_color(style.Border.border_right_color);
|
||||||
|
let bottom_color = style.resolve_color(style.Border.border_bottom_color);
|
||||||
|
let left_color = style.resolve_color(style.Border.border_left_color);
|
||||||
|
let top_style = style.Border.border_top_style;
|
||||||
|
let right_style = style.Border.border_right_style;
|
||||||
|
let bottom_style = style.Border.border_bottom_style;
|
||||||
|
let left_style = style.Border.border_left_style;
|
||||||
|
|
||||||
|
|
||||||
|
list.with_mut(|list| {
|
||||||
|
let border_display_item = ~BorderDisplayItem {
|
||||||
|
base: BaseDisplayItem {
|
||||||
|
bounds: bg_rect,
|
||||||
|
extra: ExtraDisplayListData::new(self),
|
||||||
|
},
|
||||||
|
border: border.clone(),
|
||||||
|
color: SideOffsets2D::new(top_color.to_gfx_color(),
|
||||||
|
right_color.to_gfx_color(),
|
||||||
|
bottom_color.to_gfx_color(),
|
||||||
|
left_color.to_gfx_color()),
|
||||||
|
style: SideOffsets2D::new(top_style,
|
||||||
|
right_style,
|
||||||
|
bottom_style,
|
||||||
|
left_style)
|
||||||
|
};
|
||||||
|
|
||||||
|
list.append_item(BorderDisplayItemClass(border_display_item))
|
||||||
|
});
|
||||||
|
|
||||||
|
bg_rect.origin.x = bg_rect.origin.x + border.left;
|
||||||
|
bg_rect.size.width = bg_rect.size.width - border.left - border.right;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&None => {}
|
&None => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/// 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,
|
||||||
|
list: &RefCell<DisplayList<E>>,
|
||||||
|
absolute_bounds: &Rect<Au>) {
|
||||||
|
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
||||||
|
// needed. We could use display list optimization to clean this up, but it still seems
|
||||||
|
// inefficient. What we really want is something like "nearest ancestor element that
|
||||||
|
// doesn't have a box".
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let background_color = style.resolve_color(style.Background.background_color);
|
let background_color = style.resolve_color(style.Background.background_color);
|
||||||
if !background_color.alpha.approx_eq(&0.0) {
|
if !background_color.alpha.approx_eq(&0.0) {
|
||||||
|
@ -714,11 +910,16 @@ impl Box {
|
||||||
let bottom_style = style.Border.border_bottom_style;
|
let bottom_style = style.Border.border_bottom_style;
|
||||||
let left_style = style.Border.border_left_style;
|
let left_style = style.Border.border_left_style;
|
||||||
|
|
||||||
|
let mut abs_bounds = abs_bounds.clone();
|
||||||
|
abs_bounds.origin.x = abs_bounds.origin.x + self.noncontent_inline_left();
|
||||||
|
abs_bounds.size.width = abs_bounds.size.width - self.noncontent_inline_left()
|
||||||
|
- self.noncontent_inline_right();
|
||||||
|
|
||||||
// Append the border to the display list.
|
// Append the border to the display list.
|
||||||
list.with_mut(|list| {
|
list.with_mut(|list| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: *abs_bounds,
|
bounds: abs_bounds,
|
||||||
extra: ExtraDisplayListData::new(self),
|
extra: ExtraDisplayListData::new(self),
|
||||||
},
|
},
|
||||||
border: border,
|
border: border,
|
||||||
|
@ -774,8 +975,9 @@ impl Box {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.paint_inline_background_border_if_applicable(list, &absolute_box_bounds, &offset);
|
||||||
// Add the background to the list, if applicable.
|
// Add the background to the list, if applicable.
|
||||||
self.paint_background_if_applicable(list, &absolute_box_bounds, &offset);
|
self.paint_background_if_applicable(list, &absolute_box_bounds);
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
||||||
|
@ -802,7 +1004,6 @@ impl Box {
|
||||||
&Some(ref info) => {
|
&Some(ref info) => {
|
||||||
for data in info.parent_info.rev_iter() {
|
for data in info.parent_info.rev_iter() {
|
||||||
let parent_info = FlowFlagsInfo::new(data.style.get());
|
let parent_info = FlowFlagsInfo::new(data.style.get());
|
||||||
//FIXME(ksh8281) avoid copy
|
|
||||||
flow_flags.propagate_text_decoration_from_parent(&parent_info);
|
flow_flags.propagate_text_decoration_from_parent(&parent_info);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -813,11 +1014,18 @@ impl Box {
|
||||||
text_flags.set_override_overline(flow_flags.flags.override_overline());
|
text_flags.set_override_overline(flow_flags.flags.override_overline());
|
||||||
text_flags.set_override_line_through(flow_flags.flags.override_line_through());
|
text_flags.set_override_line_through(flow_flags.flags.override_line_through());
|
||||||
|
|
||||||
|
let mut bounds = absolute_box_bounds.clone();
|
||||||
|
bounds.origin.x = bounds.origin.x + self.noncontent_left()
|
||||||
|
+ self.noncontent_inline_left();
|
||||||
|
bounds.size.width = bounds.size.width - self.noncontent_width()
|
||||||
|
- self.noncontent_inline_left()
|
||||||
|
- self.noncontent_inline_right();
|
||||||
|
|
||||||
// Create the text box.
|
// Create the text box.
|
||||||
list.with_mut(|list| {
|
list.with_mut(|list| {
|
||||||
let text_display_item = ~TextDisplayItem {
|
let text_display_item = ~TextDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: bounds,
|
||||||
extra: ExtraDisplayListData::new(self),
|
extra: ExtraDisplayListData::new(self),
|
||||||
},
|
},
|
||||||
text_run: text_box.run.clone(),
|
text_run: text_box.run.clone(),
|
||||||
|
@ -924,6 +1132,15 @@ impl Box {
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut image_ref = image_box.image.borrow_mut();
|
let mut image_ref = image_box.image.borrow_mut();
|
||||||
|
let mut bounds = absolute_box_bounds.clone();
|
||||||
|
bounds.origin.x = bounds.origin.x + self.noncontent_left()
|
||||||
|
+ self.noncontent_inline_left();
|
||||||
|
bounds.origin.y = bounds.origin.y + self.noncontent_top();
|
||||||
|
bounds.size.width = bounds.size.width
|
||||||
|
- self.noncontent_width() - self.noncontent_inline_left()
|
||||||
|
- self.noncontent_inline_right();
|
||||||
|
bounds.size.height = bounds.size.height - self.noncontent_height();
|
||||||
|
|
||||||
match image_ref.get().get_image() {
|
match image_ref.get().get_image() {
|
||||||
Some(image) => {
|
Some(image) => {
|
||||||
debug!("(building display list) building image box");
|
debug!("(building display list) building image box");
|
||||||
|
@ -932,7 +1149,7 @@ impl Box {
|
||||||
list.with_mut(|list| {
|
list.with_mut(|list| {
|
||||||
let image_display_item = ~ImageDisplayItem {
|
let image_display_item = ~ImageDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: bounds,
|
||||||
extra: ExtraDisplayListData::new(self),
|
extra: ExtraDisplayListData::new(self),
|
||||||
},
|
},
|
||||||
image: image.clone(),
|
image: image.clone(),
|
||||||
|
@ -947,6 +1164,26 @@ impl Box {
|
||||||
debug!("(building display list) no image :(");
|
debug!("(building display list) no image :(");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
||||||
|
// should have a real `SERVO_DEBUG` system.
|
||||||
|
debug!("{:?}", {
|
||||||
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
|
list.with_mut(|list| {
|
||||||
|
let border_display_item = ~BorderDisplayItem {
|
||||||
|
base: BaseDisplayItem {
|
||||||
|
bounds: absolute_box_bounds,
|
||||||
|
extra: ExtraDisplayListData::new(self),
|
||||||
|
},
|
||||||
|
border: debug_border,
|
||||||
|
color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
|
||||||
|
style: SideOffsets2D::new_all_same(border_style::solid)
|
||||||
|
|
||||||
|
};
|
||||||
|
list.append_item(BorderDisplayItemClass(border_display_item))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1149,7 +1386,8 @@ impl Box {
|
||||||
|
|
||||||
let left_box = if left_range.length() > 0 {
|
let left_box = if left_range.length() > 0 {
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), 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 mut new_metrics = new_text_box_info.run.get().metrics_for_range(&left_range);
|
||||||
|
new_metrics.bounding_box.size.height = self.position.get().size.height;
|
||||||
Some(self.transform(new_metrics.bounding_box.size,
|
Some(self.transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info)))
|
ScannedTextBox(new_text_box_info)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1158,7 +1396,8 @@ impl Box {
|
||||||
|
|
||||||
let right_box = right_range.map_default(None, |range: Range| {
|
let right_box = right_range.map_default(None, |range: Range| {
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), 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 mut new_metrics = new_text_box_info.run.get().metrics_for_range(&range);
|
||||||
|
new_metrics.bounding_box.size.height = self.position.get().size.height;
|
||||||
Some(self.transform(new_metrics.bounding_box.size,
|
Some(self.transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info)))
|
ScannedTextBox(new_text_box_info)))
|
||||||
});
|
});
|
||||||
|
@ -1166,6 +1405,12 @@ impl Box {
|
||||||
if pieces_processed_count == 1 || left_box.is_none() {
|
if pieces_processed_count == 1 || left_box.is_none() {
|
||||||
SplitDidNotFit(left_box, right_box)
|
SplitDidNotFit(left_box, right_box)
|
||||||
} else {
|
} else {
|
||||||
|
if left_box.is_some() {
|
||||||
|
left_box.get_ref().clear_noncontent_inline_right();
|
||||||
|
}
|
||||||
|
if right_box.is_some() {
|
||||||
|
right_box.get_ref().clear_noncontent_inline_left();
|
||||||
|
}
|
||||||
SplitDidFit(left_box, right_box)
|
SplitDidFit(left_box, right_box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1212,11 +1457,15 @@ impl Box {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut position = self.position.borrow_mut();
|
let mut position = self.position.borrow_mut();
|
||||||
position.get().size.width = width;
|
position.get().size.width = width + self.noncontent_width() +
|
||||||
|
self.noncontent_inline_left() + self.noncontent_inline_right();
|
||||||
image_box_info.computed_width.set(Some(width));
|
image_box_info.computed_width.set(Some(width));
|
||||||
}
|
}
|
||||||
ScannedTextBox(_) => {
|
ScannedTextBox(_) => {
|
||||||
// Scanned text boxes will have already had their widths assigned by this point.
|
// Scanned text boxes will have already had their content_widths assigned by this point.
|
||||||
|
let mut position = self.position.borrow_mut();
|
||||||
|
position.get().size.width = position.get().size.width + self.noncontent_width() +
|
||||||
|
self.noncontent_inline_left() + self.noncontent_inline_right();
|
||||||
}
|
}
|
||||||
UnscannedTextBox(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextBox(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
||||||
}
|
}
|
||||||
|
@ -1252,11 +1501,14 @@ impl Box {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut position = self.position.borrow_mut();
|
let mut position = self.position.borrow_mut();
|
||||||
position.get().size.height = height;
|
|
||||||
image_box_info.computed_height.set(Some(height));
|
image_box_info.computed_height.set(Some(height));
|
||||||
|
position.get().size.height = height + self.noncontent_height()
|
||||||
}
|
}
|
||||||
ScannedTextBox(_) => {
|
ScannedTextBox(_) => {
|
||||||
// Scanned text boxes will have already had their widths assigned by this point.
|
// Scanned text boxes will have already had their widths assigned by this point
|
||||||
|
let mut position = self.position.borrow_mut();
|
||||||
|
position.get().size.height
|
||||||
|
= position.get().size.height + self.noncontent_height()
|
||||||
}
|
}
|
||||||
UnscannedTextBox(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextBox(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use layout::float_context::FloatType;
|
||||||
use layout::flow::{BaseFlow, Flow, LeafSet, MutableOwnedFlowUtils};
|
use layout::flow::{BaseFlow, Flow, LeafSet, MutableOwnedFlowUtils};
|
||||||
use layout::inline::InlineFlow;
|
use layout::inline::InlineFlow;
|
||||||
use layout::text::TextRunScanner;
|
use layout::text::TextRunScanner;
|
||||||
use layout::util::LayoutDataAccess;
|
use layout::util::{LayoutDataAccess, OpaqueNode};
|
||||||
use layout::wrapper::{LayoutNode, PostorderNodeMutTraversal};
|
use layout::wrapper::{LayoutNode, PostorderNodeMutTraversal};
|
||||||
|
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
|
@ -442,10 +442,8 @@ impl<'fc> FlowConstructor<'fc> {
|
||||||
ConstructionItemConstructionResult(InlineBoxesConstructionItem(
|
ConstructionItemConstructionResult(InlineBoxesConstructionItem(
|
||||||
InlineBoxesConstructionResult {
|
InlineBoxesConstructionResult {
|
||||||
splits: opt_splits,
|
splits: opt_splits,
|
||||||
boxes: mut boxes
|
boxes: boxes
|
||||||
})) => {
|
})) => {
|
||||||
// fill inline info
|
|
||||||
self.set_inline_info_for_inline_child(&mut boxes, node);
|
|
||||||
|
|
||||||
// Bubble up {ib} splits.
|
// Bubble up {ib} splits.
|
||||||
match opt_splits {
|
match opt_splits {
|
||||||
|
@ -474,6 +472,49 @@ impl<'fc> FlowConstructor<'fc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill inline info
|
||||||
|
match opt_inline_block_splits {
|
||||||
|
Some(ref splits) => {
|
||||||
|
match opt_box_accumulator {
|
||||||
|
Some(ref boxes) => {
|
||||||
|
// Both
|
||||||
|
let mut total: ~[&Box] = ~[];
|
||||||
|
for split in splits.iter() {
|
||||||
|
for box_ in split.predecessor_boxes.iter() {
|
||||||
|
total.push(box_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for box_ in boxes.iter() {
|
||||||
|
total.push(box_);
|
||||||
|
}
|
||||||
|
self.set_inline_info_for_inline_child(&total, node);
|
||||||
|
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let mut total: ~[&Box] = ~[];
|
||||||
|
for split in splits.iter() {
|
||||||
|
for box_ in split.predecessor_boxes.iter() {
|
||||||
|
total.push(box_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.set_inline_info_for_inline_child(&total, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
match opt_box_accumulator {
|
||||||
|
Some(ref boxes) => {
|
||||||
|
let mut total: ~[&Box] = ~[];
|
||||||
|
for box_ in boxes.iter() {
|
||||||
|
total.push(box_);
|
||||||
|
}
|
||||||
|
self.set_inline_info_for_inline_child(&total, node);
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, make a new construction result.
|
// Finally, make a new construction result.
|
||||||
if opt_inline_block_splits.len() > 0 || opt_box_accumulator.len() > 0 {
|
if opt_inline_block_splits.len() > 0 || opt_box_accumulator.len() > 0 {
|
||||||
let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult {
|
let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult {
|
||||||
|
@ -486,7 +527,7 @@ impl<'fc> FlowConstructor<'fc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_inline_info_for_inline_child(&mut self, boxes: &mut ~[Box], parent_node: LayoutNode) {
|
fn set_inline_info_for_inline_child(&mut self, boxes: &~[&Box], parent_node: LayoutNode) {
|
||||||
let parent_box = self.build_box_for_node(parent_node);
|
let parent_box = self.build_box_for_node(parent_node);
|
||||||
let font_style = parent_box.font_style();
|
let font_style = parent_box.font_style();
|
||||||
let font_group = self.font_context.get_resolved_font_for_style(&font_style);
|
let font_group = self.font_context.get_resolved_font_for_style(&font_style);
|
||||||
|
@ -496,23 +537,35 @@ impl<'fc> FlowConstructor<'fc> {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
for box_ in boxes.mut_iter() {
|
let boxes_len = boxes.len();
|
||||||
|
parent_box.compute_borders(parent_box.style());
|
||||||
|
|
||||||
|
for (i,box_) in boxes.iter().enumerate() {
|
||||||
if box_.inline_info.with( |data| data.is_none() ) {
|
if box_.inline_info.with( |data| data.is_none() ) {
|
||||||
box_.inline_info.set(Some(InlineInfo::new()));
|
box_.inline_info.set(Some(InlineInfo::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut border = parent_box.border.get();
|
||||||
|
if i != 0 {
|
||||||
|
border.left = Zero::zero();
|
||||||
|
}
|
||||||
|
if i != (boxes_len - 1) {
|
||||||
|
border.right = Zero::zero();
|
||||||
|
}
|
||||||
|
|
||||||
let mut info = box_.inline_info.borrow_mut();
|
let mut info = box_.inline_info.borrow_mut();
|
||||||
match info.get() {
|
match info.get() {
|
||||||
&Some(ref mut info) => {
|
&Some(ref mut info) => {
|
||||||
// TODO(ksh8281) compute margin,border,padding
|
// TODO(ksh8281) compute margin,padding
|
||||||
info.parent_info.push(
|
info.parent_info.push(
|
||||||
InlineParentInfo {
|
InlineParentInfo {
|
||||||
padding: Zero::zero(),
|
padding: Zero::zero(),
|
||||||
border: Zero::zero(),
|
border: border,
|
||||||
margin: Zero::zero(),
|
margin: Zero::zero(),
|
||||||
style: parent_box.style.clone(),
|
style: parent_box.style.clone(),
|
||||||
font_ascent: font_ascent,
|
font_ascent: font_ascent,
|
||||||
font_descent: font_descent,
|
font_descent: font_descent,
|
||||||
|
node: OpaqueNode::from_layout_node(&parent_node),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
&None => {}
|
&None => {}
|
||||||
|
@ -670,13 +723,22 @@ fn strip_ignorable_whitespace_from_start(opt_boxes: &mut Option<~[Box]>) {
|
||||||
// FIXME(pcwalton): This is slow because vector shift is broken. :(
|
// FIXME(pcwalton): This is slow because vector shift is broken. :(
|
||||||
let mut found_nonwhitespace = false;
|
let mut found_nonwhitespace = false;
|
||||||
let mut result = ~[];
|
let mut result = ~[];
|
||||||
|
let mut last_removed_box: Option<Box> = None;
|
||||||
for box_ in boxes.move_iter() {
|
for box_ in boxes.move_iter() {
|
||||||
if !found_nonwhitespace && box_.is_whitespace_only() {
|
if !found_nonwhitespace && box_.is_whitespace_only() {
|
||||||
debug!("stripping ignorable whitespace from start");
|
debug!("stripping ignorable whitespace from start");
|
||||||
|
last_removed_box = Some(box_);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
found_nonwhitespace = true;
|
found_nonwhitespace = true;
|
||||||
|
match last_removed_box {
|
||||||
|
Some(ref last_removed_box) => {
|
||||||
|
box_.merge_noncontent_inline_left(last_removed_box);
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
last_removed_box = None;
|
||||||
result.push(box_)
|
result.push(box_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -692,7 +754,10 @@ fn strip_ignorable_whitespace_from_end(opt_boxes: &mut Option<~[Box]>) {
|
||||||
Some(ref mut boxes) => {
|
Some(ref mut boxes) => {
|
||||||
while boxes.len() > 0 && boxes.last().is_whitespace_only() {
|
while boxes.len() > 0 && boxes.last().is_whitespace_only() {
|
||||||
debug!("stripping ignorable whitespace from end");
|
debug!("stripping ignorable whitespace from end");
|
||||||
let _ = boxes.pop();
|
let box_ = boxes.pop();
|
||||||
|
if boxes.len() > 0 {
|
||||||
|
boxes[boxes.len() - 1].merge_noncontent_inline_right(&box_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,6 +363,7 @@ impl FlowFlagsInfo {
|
||||||
|
|
||||||
if !self.flags.is_text_decoration_enabled() && parent.flags.is_text_decoration_enabled() {
|
if !self.flags.is_text_decoration_enabled() && parent.flags.is_text_decoration_enabled() {
|
||||||
self.rare_flow_flags = parent.rare_flow_flags.clone();
|
self.rare_flow_flags = parent.rare_flow_flags.clone();
|
||||||
|
self.flags.set_text_decoration_override(parent.flags);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -646,6 +646,7 @@ impl Flow for InlineFlow {
|
||||||
|
|
||||||
for box_ in self.boxes.iter() {
|
for box_ in self.boxes.iter() {
|
||||||
debug!("Flow[{:d}]: measuring {:s}", self.base.id, box_.debug_str());
|
debug!("Flow[{:d}]: measuring {:s}", self.base.id, box_.debug_str());
|
||||||
|
box_.compute_borders(box_.style());
|
||||||
let (this_minimum_width, this_preferred_width) =
|
let (this_minimum_width, this_preferred_width) =
|
||||||
box_.minimum_and_preferred_widths();
|
box_.minimum_and_preferred_widths();
|
||||||
min_width = Au::max(min_width, this_minimum_width);
|
min_width = Au::max(min_width, this_minimum_width);
|
||||||
|
@ -710,7 +711,6 @@ impl Flow for InlineFlow {
|
||||||
//
|
//
|
||||||
// TODO(pcwalton): Cache the linebox scanner?
|
// TODO(pcwalton): Cache the linebox scanner?
|
||||||
debug!("assign_height_inline: floats_in: {:?}", self.base.floats_in);
|
debug!("assign_height_inline: floats_in: {:?}", self.base.floats_in);
|
||||||
|
|
||||||
// assign height for inline boxes
|
// assign height for inline boxes
|
||||||
for box_ in self.boxes.iter() {
|
for box_ in self.boxes.iter() {
|
||||||
box_.assign_height();
|
box_.assign_height();
|
||||||
|
@ -720,7 +720,6 @@ impl Flow for InlineFlow {
|
||||||
|
|
||||||
// Access the linebox scanner.
|
// Access the linebox scanner.
|
||||||
scanner.scan_for_lines(self);
|
scanner.scan_for_lines(self);
|
||||||
|
|
||||||
let mut line_height_offset = Au::new(0);
|
let mut line_height_offset = Au::new(0);
|
||||||
|
|
||||||
// All lines use text alignment of the flow.
|
// All lines use text alignment of the flow.
|
||||||
|
@ -743,6 +742,7 @@ impl Flow for InlineFlow {
|
||||||
|
|
||||||
for box_i in line.range.eachi() {
|
for box_i in line.range.eachi() {
|
||||||
let cur_box = &self.boxes[box_i];
|
let cur_box = &self.boxes[box_i];
|
||||||
|
let top = cur_box.noncontent_top();
|
||||||
|
|
||||||
// FIXME(pcwalton): Move into `box.rs` like the rest of box-specific layout code?
|
// 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 {
|
let (top_from_base, bottom_from_base, ascent) = match cur_box.specific {
|
||||||
|
@ -751,22 +751,10 @@ impl Flow for InlineFlow {
|
||||||
|
|
||||||
// TODO: margin, border, padding's top and bottom should be calculated in
|
// TODO: margin, border, padding's top and bottom should be calculated in
|
||||||
// advance, since baseline of image is bottom margin edge.
|
// advance, since baseline of image is bottom margin edge.
|
||||||
let mut top;
|
let bottom = cur_box.noncontent_bottom();
|
||||||
let mut bottom;
|
|
||||||
{
|
|
||||||
top = cur_box.border.get().top + cur_box.padding.get().top +
|
|
||||||
cur_box.margin.get().top;
|
|
||||||
bottom = cur_box.border.get().bottom + cur_box.padding.get().bottom +
|
|
||||||
cur_box.margin.get().bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
let noncontent_height = top + bottom;
|
let noncontent_height = top + bottom;
|
||||||
height = height + noncontent_height;
|
height = height + noncontent_height;
|
||||||
|
|
||||||
let mut position_ref = cur_box.position.borrow_mut();
|
|
||||||
position_ref.get().size.height = height;
|
|
||||||
position_ref.get().translate(&Point2D(Au::new(0), -height));
|
|
||||||
|
|
||||||
let ascent = height + bottom;
|
let ascent = height + bottom;
|
||||||
(height, Au::new(0), ascent)
|
(height, Au::new(0), ascent)
|
||||||
},
|
},
|
||||||
|
@ -845,7 +833,7 @@ impl Flow for InlineFlow {
|
||||||
bottommost = bottom_from_base;
|
bottommost = bottom_from_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_box.position.borrow_mut().get().origin.y = line.bounds.origin.y + offset;
|
cur_box.position.borrow_mut().get().origin.y = line.bounds.origin.y + offset + top;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the distance from baseline to the top of the biggest box with 'bottom'
|
// Calculate the distance from baseline to the top of the biggest box with 'bottom'
|
||||||
|
|
|
@ -18,12 +18,14 @@ use style::computed_values::white_space;
|
||||||
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
|
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
|
||||||
pub struct TextRunScanner {
|
pub struct TextRunScanner {
|
||||||
clump: Range,
|
clump: Range,
|
||||||
|
last_lost_box_index: Option<uint>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextRunScanner {
|
impl TextRunScanner {
|
||||||
pub fn new() -> TextRunScanner {
|
pub fn new() -> TextRunScanner {
|
||||||
TextRunScanner {
|
TextRunScanner {
|
||||||
clump: Range::empty(),
|
clump: Range::empty(),
|
||||||
|
last_lost_box_index: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +104,8 @@ impl TextRunScanner {
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
// FIXME(pcwalton): Stop cloning boxes, as above.
|
// FIXME(pcwalton): Stop cloning boxes, as above.
|
||||||
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
|
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
|
||||||
out_boxes.push(in_boxes[self.clump.begin()].clone());
|
let new_box = in_boxes[self.clump.begin()].clone();
|
||||||
|
self.push_to_outboxes(new_box,in_boxes,out_boxes);
|
||||||
},
|
},
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
let old_box = &in_boxes[self.clump.begin()];
|
let old_box = &in_boxes[self.clump.begin()];
|
||||||
|
@ -145,7 +148,9 @@ impl TextRunScanner {
|
||||||
let mut new_box = old_box.transform(new_metrics.bounding_box.size,
|
let mut new_box = old_box.transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info));
|
ScannedTextBox(new_text_box_info));
|
||||||
new_box.new_line_pos = new_line_pos;
|
new_box.new_line_pos = new_line_pos;
|
||||||
out_boxes.push(new_box)
|
self.push_to_outboxes(new_box,in_boxes,out_boxes);
|
||||||
|
} else {
|
||||||
|
self.last_lost_box_index = Some(self.clump.begin());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(false, true) => {
|
(false, true) => {
|
||||||
|
@ -237,7 +242,7 @@ impl TextRunScanner {
|
||||||
let mut new_box = in_boxes[i].transform(new_metrics.bounding_box.size,
|
let mut new_box = in_boxes[i].transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info));
|
ScannedTextBox(new_text_box_info));
|
||||||
new_box.new_line_pos = new_line_positions[logical_offset].new_line_pos.clone();
|
new_box.new_line_pos = new_line_positions[logical_offset].new_line_pos.clone();
|
||||||
out_boxes.push(new_box)
|
self.push_to_outboxes(new_box,in_boxes,out_boxes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // End of match.
|
} // End of match.
|
||||||
|
@ -265,4 +270,15 @@ impl TextRunScanner {
|
||||||
|
|
||||||
new_whitespace
|
new_whitespace
|
||||||
} // End of `flush_clump_to_list`.
|
} // End of `flush_clump_to_list`.
|
||||||
|
|
||||||
|
fn push_to_outboxes(&mut self, new_box: Box, in_boxes: &~[Box], out_boxes: &mut ~[Box]) {
|
||||||
|
match self.last_lost_box_index {
|
||||||
|
Some(index) => {
|
||||||
|
new_box.merge_noncontent_inline_left(&in_boxes[index]);
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
self.last_lost_box_index = None;
|
||||||
|
out_boxes.push(new_box)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<title>hi there?</title>
|
||||||
span {
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<span style="display: block;">hi there</span>
|
<p style="background:gray">
|
||||||
|
<span style="background:red;font-size:35px;border: black solid 15px">
|
||||||
|
<img src="test.jpeg" style="border:blue 30px solid;" />
|
||||||
|
kitty?
|
||||||
|
<em style="background:blue;font-size:15px;border:yellow 15px solid">
|
||||||
|
this is em
|
||||||
|
</em>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue